-
Notifications
You must be signed in to change notification settings - Fork 23
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
base: dev
Are you sure you want to change the base?
Conversation
|
This is cool! |
|
Hey, thanks a lot for your contribution! I have a lot of stuff going on in my private life lately but I will try to find some time this weekend to have a look at it. |
Exlll
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides the things that I commented: I generally try to stay below 80 chars per line. 90 chars per line is a hard limit except for some edge cases and in tests. Could you please reformat your code so that the line length is within these limits?
Also please prefix all top-level classes with Adventure, i.e. AdventureComponentSerializer, AdventureComponentFormat, etc.
Overall pretty nice work 👍
| // 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("<[^>]+>"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pattern is overly broad and matches strings like < gre eeen > and 3 < 4 and 4 > 2.
| */ | ||
| public enum ComponentFormat { | ||
| /** MiniMessage format with tags like {@code <red>} or {@code <bold>}. */ | ||
| MINI_MESSAGE(input -> Patterns.MINI_MESSAGE_PATTERN.matcher(input).find()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just use Pattern.compile("...").asPredicate()
| * @param formats the formats to use, in order of preference | ||
| */ | ||
| public ComponentSerializer(ComponentFormat... formats) { | ||
| this(Arrays.asList(formats), Arrays.asList(formats)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should make a defensive copy here, too. Calling asList is not enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I already called List.copyOf in another constructor. This constructor just converts the array to a List to pass it to the other constructor. or I miss understanding here?
| try { | ||
| return serialize(element, format); | ||
| } catch (Exception ignored) { | ||
| // This should never happen, but in case of adventure library issue | ||
| ignored.printStackTrace(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't do this.
| try { | ||
| return deserialize(element, format); | ||
| } catch (Exception ignored) { | ||
| // This should never happen, but in case of adventure library issue | ||
| ignored.printStackTrace(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't do this.
| // Key.key("default", "namespace:value") will throw InvalidKeyException because | ||
| // ':' is not allowed in value | ||
| assertThrows(Exception.class, () -> serializer.deserialize("namespace:value")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't expect Exception but InvalidKeyException in this case
| assertThat( | ||
| serializer.deserialize(new File(TMP_CONFIG_PATH)), | ||
| is("/tmp/config.yml") | ||
| is(TestUtils.isWindows() ? "C:\\tmp\\config.yml" : "/tmp/config.yml") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing this. You can use TestUtils.createPlatformSpecificFilePath here.
| @Plugin(id = "configlib", name = "ConfigLib", version = "4.8.0", url = "https://github.com/Exlll/ConfigLib", description = "A library for working with YAML configurations.", authors = { | ||
| "Exlll" }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please restore the original format.
| @Override | ||
| public String serialize(Sound element) { | ||
| StringBuilder builder = new StringBuilder(element.name().asString()); | ||
| if (element.source() != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This if statement is always true.
| public Sound deserialize(String element) { | ||
| String[] parts = element.split(DELIMINATOR); | ||
| float pitch = 1.0f; | ||
| float volume = 1.0f; | ||
| Sound.Source source = defaultSource; | ||
|
|
||
| int endIndex = parts.length - 1; | ||
|
|
||
| // Try to parse source | ||
| if (endIndex >= 0) { | ||
| try { | ||
| source = Sound.Source.valueOf(parts[endIndex]); | ||
| endIndex--; | ||
| } catch (IllegalArgumentException ignored) { | ||
| } | ||
| } | ||
|
|
||
| // Try to parse volume and pitch | ||
| if (endIndex >= 0) { | ||
| Float lastFloat = tryParseFloat(parts[endIndex]); | ||
| if (lastFloat != null) { | ||
| boolean hasSecondFloat = false; | ||
| if (endIndex > 0) { | ||
| Float secondLastFloat = tryParseFloat(parts[endIndex - 1]); | ||
| if (secondLastFloat != null) { | ||
| volume = lastFloat; | ||
| pitch = secondLastFloat; | ||
| endIndex -= 2; | ||
| hasSecondFloat = true; | ||
| } | ||
| } | ||
|
|
||
| if (!hasSecondFloat) { | ||
| pitch = lastFloat; | ||
| endIndex--; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Key key = buildKey(parts, endIndex); | ||
| return Sound.sound(key, source, volume, pitch); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parsing logic seems overly complex. Perhaps you can replace this with a Pattern? Something like this:
Pattern pattern = Pattern.compile(
"""
^(?<key>[a-zA-Z:]+)\
(?:\\s+(?<volume>\\d+(?:\\.\\d+)?)?)?\
(?:\\s+(?<pitch>\\d+(?:\\.\\d+)?)?)?\
(?:\\s+(?<source>MASTER|AMBIENT|MUSIC)?)?\
\\s*$\
""");
Matcher matcher = pattern.matcher("minecraft 0.4 MASTER");
System.out.println(matcher.matches());
System.out.println(matcher.group("key"));
System.out.println(matcher.group("volume"));
System.out.println(matcher.group("pitch"));
System.out.println(matcher.group("source"));
This pull request addresses issue #29, which I opened previously, to add native support for the Adventure API Component.
Changes in this PR
configlib-adventure, shaded into the Paper and Velocity modules (since both natively support Adventure).Component,Key, andSound.Notes
I noticed that running
gradle testat the root or within any module only executed tests in thecoremodule. I am not sure whether this behavior was intentional.I modified the behavior so that:
If the previous test configuration was intentional, please let me know and I will revert the changes accordingly.
I also fixed two failing tests in the
coremodule that were caused by Windows-specific behavior (as shown in the screenshot). All core module tests now pass on Windows.If you are not satisfied with the changes mentioned above, I am willing to revert or adjust them as needed.