From 0bbe3e6649bb9b9b7cc92a129edf5993641c15b8 Mon Sep 17 00:00:00 2001 From: Janmm14 Date: Sun, 14 Apr 2024 02:43:35 +0200 Subject: [PATCH] Improve chat api toLegacy conversion and obj toString - Legacy conversion has been pimped to output less redundant legacy codes - Fix bug introduced in 765858f17c0554a9e2e2d64479d6125b7b1c0362 of array toLegacy conversion with new methods keeping track of current string color - Fix TranslatableComponent copy constructor not copying fallback - Make TranslatableComponent format pattern static - Change ComponentBuilder.build() to return not nested component if there is just one part --- .../md_5/bungee/api/chat/BaseComponent.java | 215 +++++++++++++++--- .../bungee/api/chat/ComponentBuilder.java | 4 + .../md_5/bungee/api/chat/ComponentStyle.java | 64 ++++++ .../bungee/api/chat/KeybindComponent.java | 24 +- .../md_5/bungee/api/chat/ScoreComponent.java | 29 ++- .../bungee/api/chat/SelectorComponent.java | 28 ++- .../md_5/bungee/api/chat/TextComponent.java | 27 ++- .../api/chat/TranslatableComponent.java | 67 ++++-- .../md_5/bungee/api/chat/ComponentsTest.java | 46 +++- .../api/chat/TranslatableComponentTest.java | 25 +- 10 files changed, 448 insertions(+), 81 deletions(-) diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java index 17af2508ac5..a5b4b146461 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java @@ -6,12 +6,10 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; -import lombok.ToString; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.ComponentBuilder.FormatRetention; @Setter -@ToString(exclude = "parent") @EqualsAndHashCode(exclude = "parent") public abstract class BaseComponent { @@ -215,9 +213,12 @@ public BaseComponent duplicateWithoutFormatting() public static String toLegacyText(BaseComponent... components) { StringBuilder builder = new StringBuilder(); + ComponentStyle currentStyle = new ComponentStyle(); + currentStyle.setColor( ChatColor.RESET ); + for ( BaseComponent msg : components ) { - builder.append( msg.toLegacyText() ); + currentStyle = msg.toLegacyText( builder, currentStyle ); } return builder.toString(); } @@ -273,15 +274,20 @@ public void setColor(ChatColor color) */ public ChatColor getColor() { - if ( !style.hasColor() ) + return getColor( ChatColor.WHITE ); + } + + ChatColor getColor(ChatColor def) + { + if ( style.hasColor() ) { - if ( parent == null ) - { - return ChatColor.WHITE; - } - return parent.getColor(); + return style.getColor(); } - return style.getColor(); + if ( parent == null ) + { + return def; + } + return parent.getColor( def ); } /** @@ -651,46 +657,199 @@ void toPlainText(StringBuilder builder) public String toLegacyText() { StringBuilder builder = new StringBuilder(); - toLegacyText( builder ); + ComponentStyle currentLegacy = new ComponentStyle(); + currentLegacy.setColor( ChatColor.RESET ); + toLegacyText( builder, currentLegacy ); return builder.toString(); } - void toLegacyText(StringBuilder builder) + /** + * Converts the component to a string that uses the old formatting codes + * ({@link net.md_5.bungee.api.ChatColor#COLOR_CHAR} + * + * @param currentLegacy the style at the end of the string the result of this method will be appended to + * @return the string in the old format + */ + public String toLegacyText(ComponentStyle currentLegacy) { - if ( extra != null ) + StringBuilder builder = new StringBuilder(); + toLegacyText( builder, currentLegacy ); + return builder.toString(); + } + + /** + * Converts the component to a string that uses the old formatting codes + * ({@link net.md_5.bungee.api.ChatColor#COLOR_CHAR} + * + * @param builder the StringBuilder to append to + * @param currentLegacy the style at the end of {@code builder} + * @return the style at the end of the legacy string + */ + public ComponentStyle toLegacyText(StringBuilder builder, ComponentStyle currentLegacy) + { + currentLegacy = currentLegacy.clone(); + if ( !currentLegacy.hasColor() ) { - for ( BaseComponent e : extra ) + currentLegacy.setColor( ChatColor.RESET ); + } + return toLegacyText( builder, currentLegacy.hasColor() ? currentLegacy.getColor() : ChatColor.RESET, currentLegacy ); + } + + /** + * Converts the component to a string that uses the old formatting codes + * ({@link net.md_5.bungee.api.ChatColor#COLOR_CHAR} + * + * @param builder the StringBuilder to append to + * @param baseColor the color to use if no color is set, but a format downgrade is needed + * @param currentLegacy the style at the end of {@code builder} + * @return the new current style at the end of the {@code builder} + */ + ComponentStyle toLegacyText(StringBuilder builder, ChatColor baseColor, ComponentStyle currentLegacy) + { + if ( extra == null ) + { + return currentLegacy; + } + for ( BaseComponent e : extra ) + { + currentLegacy = e.toLegacyText( builder, baseColor, currentLegacy ); + } + return currentLegacy; + } + + private static boolean colorEquals(ChatColor a, ChatColor b) + { + if ( a == b ) + { + return true; + } + if ( a == null || b == null ) + { + return false; + } + if ( ChatColor.RESET.equals( a ) ) + { + return ChatColor.WHITE.equals( b ) || ChatColor.RESET.equals( b ); + } + if ( ChatColor.RESET.equals( b ) ) + { + return ChatColor.WHITE.equals( a ) || ChatColor.RESET.equals( a ); + } + return a.equals( b ); + } + + /** + * @param builder the StringBuilder to append to + * @param baseColor the color to use if no color is set, but a format downgrade is needed + * @param currentLegacy the style at the end of {@code builder} + * @return the new current style at the end of {@code builder} + */ + ComponentStyle addFormat(StringBuilder builder, ChatColor baseColor, ComponentStyle currentLegacy) + { + // Check if we can skip adding color code + if ( colorEquals( getColor(), currentLegacy.getColor() ) && currentLegacy.isLegacyFormattingUpgrade( style ) ) + { + if ( isBold() && !currentLegacy.isBold() ) + { + builder.append( ChatColor.BOLD ); + } + if ( isItalic() && !currentLegacy.isItalic() ) + { + builder.append( ChatColor.ITALIC ); + } + if ( isUnderlined() && !currentLegacy.isUnderlined() ) + { + builder.append( ChatColor.UNDERLINE ); + } + if ( isStrikethrough() && !currentLegacy.isStrikethrough() ) { - e.toLegacyText( builder ); + builder.append( ChatColor.STRIKETHROUGH ); } + if ( isObfuscated() && !currentLegacy.isObfuscated() ) + { + builder.append( ChatColor.MAGIC ); + } + } else + { + builder.append( getColor( baseColor ) == null ? baseColor : getColor( baseColor ) ); + if ( isBold() ) + { + builder.append( ChatColor.BOLD ); + } + if ( isItalic() ) + { + builder.append( ChatColor.ITALIC ); + } + if ( isUnderlined() ) + { + builder.append( ChatColor.UNDERLINE ); + } + if ( isStrikethrough() ) + { + builder.append( ChatColor.STRIKETHROUGH ); + } + if ( isObfuscated() ) + { + builder.append( ChatColor.MAGIC ); + } + } + currentLegacy = style; + if ( currentLegacy.getColor() == null ) + { + currentLegacy = style.clone(); + currentLegacy.setColor( getColor( baseColor ) == null ? baseColor : getColor( baseColor ) ); } + return currentLegacy; } - void addFormat(StringBuilder builder) + @Override + public String toString() { - if ( style.hasColor() || parent != null ) + StringBuilder builder = new StringBuilder( toStringName() ).append( "{" ); + toString( builder, false ); + return builder.append( "}" ).toString(); + } + + String toStringName() + { + return "BaseComponent"; + } + + boolean toString(StringBuilder builder, boolean comma) + { + if ( style != null ) { - builder.append( getColor() ); + comma = style.toString( builder, comma ); } - if ( isBold() ) + if ( insertion != null ) { - builder.append( ChatColor.BOLD ); + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "insertion=" ).append( insertion ); } - if ( isItalic() ) + if ( clickEvent != null ) { - builder.append( ChatColor.ITALIC ); + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "clickEvent=" ).append( clickEvent ); } - if ( isUnderlined() ) + if ( hoverEvent != null ) { - builder.append( ChatColor.UNDERLINE ); + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "hoverEvent=" ).append( hoverEvent ); } - if ( isStrikethrough() ) + if ( reset ) { - builder.append( ChatColor.STRIKETHROUGH ); + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "reset" ); } - if ( isObfuscated() ) + if ( extra != null ) { - builder.append( ChatColor.MAGIC ); + if ( comma ) builder.append( ", " ); + builder.append( "extra=" ).append( extra ); } + return comma; } } diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java b/chat/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java index 9ddb92e330a..ecc3a469d4a 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java @@ -501,6 +501,10 @@ public ComponentBuilder retain(FormatRetention retention) */ public BaseComponent build() { + if ( parts.size() == 1 ) + { + return parts.get( 0 ).duplicate(); + } TextComponent base = new TextComponent(); if ( !parts.isEmpty() ) { diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/ComponentStyle.java b/chat/src/main/java/net/md_5/bungee/api/chat/ComponentStyle.java index 15f44ea730c..acc930fe911 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/ComponentStyle.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/ComponentStyle.java @@ -200,6 +200,70 @@ public boolean isEmpty() && strikethrough == null && obfuscated == null; } + @Override + public String toString() + { + StringBuilder builder = new StringBuilder( "ComponentStyle{" ); + toString( builder, false ); + return builder.append( "}" ).toString(); + } + + boolean toString(StringBuilder builder, boolean comma) + { + if ( color != null ) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "color=" ).append( color ); + } + if ( font != null ) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "font=" ).append( font ).append( ", " ); + } + if ( bold != null ) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "bold=" ).append( bold ); + } + if ( italic != null ) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "italic=" ).append( italic ); + } + if ( underlined != null ) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "underlined=" ).append( underlined ); + } + if ( strikethrough != null ) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "strikethrough=" ).append( strikethrough ); + } + if ( obfuscated != null ) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "obfuscated=" ).append( obfuscated ); + } + return comma; + } + + boolean isLegacyFormattingUpgrade(ComponentStyle newStyle) + { + return ( newStyle.isBold() || !isBold() ) + && ( newStyle.isItalic() || !isItalic() ) + && ( newStyle.isUnderlined() || !isUnderlined() ) + && ( newStyle.isStrikethrough() || !isStrikethrough() ) + && ( newStyle.isObfuscated() || !isObfuscated() ); + } + @Override public ComponentStyle clone() { diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/KeybindComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/KeybindComponent.java index 4cefe259bd7..6806e2584bf 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/KeybindComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/KeybindComponent.java @@ -4,11 +4,10 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import lombok.ToString; +import net.md_5.bungee.api.ChatColor; @Getter @Setter -@ToString @NoArgsConstructor @EqualsAndHashCode(callSuper = true) public final class KeybindComponent extends BaseComponent @@ -57,10 +56,25 @@ protected void toPlainText(StringBuilder builder) } @Override - protected void toLegacyText(StringBuilder builder) + ComponentStyle toLegacyText(StringBuilder builder, ChatColor baseColor, ComponentStyle currentLegacy) { - addFormat( builder ); + currentLegacy = addFormat( builder, baseColor, currentLegacy ); builder.append( getKeybind() ); - super.toLegacyText( builder ); + return super.toLegacyText( builder, baseColor, currentLegacy ); + } + + @Override + String toStringName() + { + return "Keybind"; + } + + @Override + boolean toString(StringBuilder builder, boolean comma) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "keybind=" ).append( keybind ); + return super.toString( builder, comma ); } } diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/ScoreComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/ScoreComponent.java index ebf7bb31421..8a2c13364ec 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/ScoreComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/ScoreComponent.java @@ -4,7 +4,7 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; -import lombok.ToString; +import net.md_5.bungee.api.ChatColor; /** * This component displays the score based on a player score on the scoreboard. @@ -25,7 +25,6 @@ */ @Getter @Setter -@ToString @AllArgsConstructor @EqualsAndHashCode(callSuper = true) public final class ScoreComponent extends BaseComponent @@ -92,10 +91,30 @@ protected void toPlainText(StringBuilder builder) } @Override - protected void toLegacyText(StringBuilder builder) + ComponentStyle toLegacyText(StringBuilder builder, ChatColor baseColor, ComponentStyle currentLegacy) { - addFormat( builder ); + currentLegacy = addFormat( builder, baseColor, currentLegacy ); builder.append( this.value ); - super.toLegacyText( builder ); + return super.toLegacyText( builder, baseColor, currentLegacy ); + } + + @Override + String toStringName() + { + return "Score"; + } + + @Override + boolean toString(StringBuilder builder, boolean comma) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "name=" ).append( name ).append( ", " ) + .append( "objective=" ).append( objective ); + if ( value != null ) + { + builder.append( ", " ).append( "value=" ).append( value ); + } + return super.toString( builder, comma ); } } diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/SelectorComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/SelectorComponent.java index ff1e260bcb6..c33e0117873 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/SelectorComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/SelectorComponent.java @@ -4,7 +4,7 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; -import lombok.ToString; +import net.md_5.bungee.api.ChatColor; /** * This component processes a target selector into a pre-formatted set of @@ -21,7 +21,6 @@ */ @Getter @Setter -@ToString @AllArgsConstructor @EqualsAndHashCode(callSuper = true) public final class SelectorComponent extends BaseComponent @@ -76,10 +75,29 @@ protected void toPlainText(StringBuilder builder) } @Override - protected void toLegacyText(StringBuilder builder) + ComponentStyle toLegacyText(StringBuilder builder, ChatColor baseColor, ComponentStyle currentLegacy) { - addFormat( builder ); + currentLegacy = addFormat( builder, baseColor, currentLegacy ); builder.append( this.selector ); - super.toLegacyText( builder ); + return super.toLegacyText( builder, baseColor, currentLegacy ); + } + + @Override + String toStringName() + { + return "Selector"; + } + + @Override + boolean toString(StringBuilder builder, boolean comma) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "selector=" ).append( selector ); + if ( separator != null ) + { + builder.append( ", " ).append( "separator=" ).append( separator ); + } + return super.toString( builder, comma ); } } diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java index 0971a384c70..8f62b2f29b8 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java @@ -265,7 +265,7 @@ public TextComponent(BaseComponent... extras) { return; } - setExtra( new ArrayList( Arrays.asList( extras ) ) ); + setExtra( new ArrayList<>( Arrays.asList( extras ) ) ); } /** @@ -287,16 +287,31 @@ protected void toPlainText(StringBuilder builder) } @Override - protected void toLegacyText(StringBuilder builder) + ComponentStyle toLegacyText(StringBuilder builder, ChatColor baseColor, ComponentStyle currentLegacy) { - addFormat( builder ); + // cannot eliminate formatting codes if text is empty to keep test case testFormattingOnlyTextConversion happy + // (this could be solved to always add formatting if parent == null) and to not ignore formatting at the end in + // general in case plugins are doing weird combinations with conversions + currentLegacy = addFormat( builder, baseColor, currentLegacy ); builder.append( text ); - super.toLegacyText( builder ); + return super.toLegacyText( builder, baseColor, currentLegacy ); } @Override - public String toString() + String toStringName() { - return "TextComponent{text=" + text + ", " + super.toString() + '}'; + return "Text"; + } + + @Override + boolean toString(StringBuilder builder, boolean comma) + { + if ( comma ) + { + builder.append( ", " ); + } + comma = true; + builder.append( "t=" ).append( text ); + return super.toString( builder, comma ); } } diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/TranslatableComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/TranslatableComponent.java index 13c095646ac..87a099e54d2 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/TranslatableComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/TranslatableComponent.java @@ -8,18 +8,17 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import lombok.ToString; +import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.chat.TranslationRegistry; @Getter @Setter -@ToString @NoArgsConstructor @EqualsAndHashCode(callSuper = true) public final class TranslatableComponent extends BaseComponent { - private final Pattern format = Pattern.compile( "%(?:(\\d+)\\$)?([A-Za-z%]|$)" ); + private static final Pattern format = Pattern.compile( "%(?:(\\d+)\\$)?([A-Za-z%]|$)" ); /** * The key into the Minecraft locale files to use for the translation. The @@ -44,10 +43,11 @@ public TranslatableComponent(TranslatableComponent original) { super( original ); setTranslate( original.getTranslate() ); + setFallback( original.getFallback() ); if ( original.getWith() != null ) { - List temp = new ArrayList(); + List temp = new ArrayList<>(); for ( BaseComponent baseComponent : original.getWith() ) { temp.add( baseComponent.duplicate() ); @@ -157,18 +157,18 @@ public void addWith(BaseComponent component) @Override protected void toPlainText(StringBuilder builder) { - convert( builder, false ); + convert( builder, null, null ); super.toPlainText( builder ); } @Override - protected void toLegacyText(StringBuilder builder) + ComponentStyle toLegacyText(StringBuilder builder, ChatColor baseColor, ComponentStyle currentLegacy) { - convert( builder, true ); - super.toLegacyText( builder ); + currentLegacy = convert( builder, baseColor, currentLegacy ); + return super.toLegacyText( builder, baseColor, currentLegacy ); } - private void convert(StringBuilder builder, boolean applyFormat) + private ComponentStyle convert(StringBuilder builder, ChatColor baseColor, ComponentStyle currentLegacy) { String trans = TranslationRegistry.INSTANCE.translate( translate ); @@ -185,11 +185,11 @@ private void convert(StringBuilder builder, boolean applyFormat) int pos = matcher.start(); if ( pos != position ) { - if ( applyFormat ) + if ( baseColor != null ) { - addFormat( builder ); + currentLegacy = addFormat( builder, baseColor, currentLegacy ); } - builder.append( trans.substring( position, pos ) ); + builder.append( trans, position, pos ); } position = matcher.end(); @@ -201,18 +201,18 @@ private void convert(StringBuilder builder, boolean applyFormat) String withIndex = matcher.group( 1 ); BaseComponent withComponent = with.get( withIndex != null ? Integer.parseInt( withIndex ) - 1 : i++ ); - if ( applyFormat ) + if ( baseColor != null ) { - withComponent.toLegacyText( builder ); + currentLegacy = withComponent.toLegacyText( builder, baseColor, currentLegacy ); } else { withComponent.toPlainText( builder ); } break; case '%': - if ( applyFormat ) + if ( baseColor != null ) { - addFormat( builder ); + currentLegacy = addFormat( builder, baseColor, currentLegacy ); } builder.append( '%' ); break; @@ -220,11 +220,40 @@ private void convert(StringBuilder builder, boolean applyFormat) } if ( trans.length() != position ) { - if ( applyFormat ) + if ( baseColor != null ) { - addFormat( builder ); + currentLegacy = addFormat( builder, baseColor, currentLegacy ); } - builder.append( trans.substring( position, trans.length() ) ); + builder.append( trans, position, trans.length() ); + } else if ( baseColor != null ) + { + currentLegacy = addFormat( builder, baseColor, currentLegacy ); + } + return currentLegacy; + } + + @Override + String toStringName() + { + return "Translatable"; + } + + @Override + boolean toString(StringBuilder builder, boolean comma) + { + if ( comma ) builder.append( ", " ); + comma = true; + builder.append( "translate=" ).append( translate ); + if ( with != null ) + { + builder.append( ", " ); + builder.append( "with=" ).append( with ); + } + if ( fallback != null ) + { + builder.append( ", " ); + builder.append( "fallback=" ).append( fallback ); } + return super.toString( builder, comma ); } } diff --git a/chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java b/chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java index 04dff726bda..a4c45e6584e 100644 --- a/chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java +++ b/chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java @@ -100,7 +100,7 @@ public void testArrayUUIDParse() @Test public void testEmptyComponentBuilderCreate() { - this.testEmptyComponentBuilder( + testEmptyComponentBuilder( ComponentBuilder::create, (components) -> assertEquals( components.length, 0 ), (components, size) -> assertEquals( size, components.length ) @@ -110,21 +110,22 @@ public void testEmptyComponentBuilderCreate() @Test public void testEmptyComponentBuilderBuild() { - this.testEmptyComponentBuilder( + testEmptyComponentBuilder( ComponentBuilder::build, (component) -> assertNull( component.getExtra() ), (component, size) -> assertEquals( component.getExtra().size(), size ) ); } - private void testEmptyComponentBuilder(Function componentBuilder, Consumer emptyAssertion, ObjIntConsumer sizedAssertion) + private static void testEmptyComponentBuilder(Function componentBuilder, Consumer emptyAssertion, ObjIntConsumer sizedAssertion) { ComponentBuilder builder = new ComponentBuilder(); T component = componentBuilder.apply( builder ); emptyAssertion.accept( component ); - for ( int i = 0; i < 3; i++ ) + builder.append( "part: 0" ); // build() with one part will not be nested + for ( int i = 1; i < 3; i++ ) { builder.append( "part:" + i ); component = componentBuilder.apply( builder ); @@ -191,6 +192,13 @@ public void testToLegacyFromLegacy() assertEquals( text, BaseComponent.toLegacyText( TextComponent.fromLegacyText( text ) ) ); } + @Test + public void testToLegacyFromLegacyNew() + { + String text = "" + GREEN + BOLD + "Hello " + WHITE + MAGIC + "world" + GRAY + "!"; + assertEquals( text, BaseComponent.toLegacyText( TextComponent.fromLegacy( text ) ) ); + } + @Test public void testNoColorComponent() { @@ -539,6 +547,7 @@ private static void testBuilderAppendLegacy(Function co public void testBasicComponent() { TextComponent textComponent = new TextComponent( "Hello world" ); + assertEquals( "Hello world", textComponent.toLegacyText() ); textComponent.setColor( RED ); assertEquals( "Hello world", textComponent.toPlainText() ); @@ -556,8 +565,7 @@ public void testLegacyConverter() BaseComponent[] test2 = TextComponent.fromLegacyText( "Text http://spigotmc.org " + GREEN + "google.com/test" ); assertEquals( "Text http://spigotmc.org google.com/test", BaseComponent.toPlainText( test2 ) ); - //The extra ChatColor instances are sometimes inserted when not needed but it doesn't change the result - assertEquals( "Text http://spigotmc.org " + GREEN + "google.com/test" + GREEN, BaseComponent.toLegacyText( test2 ) ); + assertEquals( "Text http://spigotmc.org " + GREEN + "google.com/test", BaseComponent.toLegacyText( test2 ) ); ClickEvent url1 = test2[1].getClickEvent(); assertNotNull( url1 ); @@ -871,4 +879,30 @@ private static String fromAndToLegacyText(String legacyText) { return BaseComponent.toLegacyText( TextComponent.fromLegacyText( legacyText ) ); } + + @Test + public void testExtraFormatting() + { + BaseComponent component = new ComponentBuilder( "Hello " ).color( GOLD ).build(); + component.addExtra( new ComponentBuilder( "World" ).bold( true ).build() ); + component.addExtra( new ComponentBuilder( "!" ).color( RED ).build() ); + component.addExtra( new ComponentBuilder( " xd" ).build() ); + + assertEquals( "Hello World! xd", component.toPlainText() ); + assertEquals( GOLD + "Hello " + BOLD + "World" + RED + "!" + GOLD + " xd", component.toLegacyText() ); + } + + @Test + public void testExtraFormattingNested() + { + BaseComponent component = new ComponentBuilder( "Hello " ).color( GOLD ).build(); + component.addExtra( new TextComponent( new ComponentBuilder( "World" ).bold( true ).build() ) ); + component.addExtra( new TextComponent( new ComponentBuilder( "!" ).color( RED ).build() ) ); + component.addExtra( new TextComponent( new ComponentBuilder( " xd" ).build() ) ); + + assertEquals( "Hello World! xd", component.toPlainText() ); + // Empty extra text componenet 2 (holding extra "!") adds the redudant gold formatting, + // see TextComponent#toLegacyText comment as to why we keep it + assertEquals( GOLD + "Hello " + BOLD + "World" + GOLD + RED + "!" + GOLD + " xd", component.toLegacyText() ); + } } diff --git a/chat/src/test/java/net/md_5/bungee/api/chat/TranslatableComponentTest.java b/chat/src/test/java/net/md_5/bungee/api/chat/TranslatableComponentTest.java index 9e1bde86cfa..1afcd5576f1 100644 --- a/chat/src/test/java/net/md_5/bungee/api/chat/TranslatableComponentTest.java +++ b/chat/src/test/java/net/md_5/bungee/api/chat/TranslatableComponentTest.java @@ -13,7 +13,7 @@ public void testMissingPlaceholdersAdded() { TranslatableComponent testComponent = new TranslatableComponent( "Test string with %s placeholders: %s", 2, "aoeu" ); assertEquals( "Test string with 2 placeholders: aoeu", testComponent.toPlainText() ); - assertEquals( "Test string with " + WHITE + "2 placeholders: " + WHITE + "aoeu", testComponent.toLegacyText() ); + assertEquals( "Test string with 2 placeholders: aoeu", testComponent.toLegacyText() ); } @Test @@ -24,28 +24,39 @@ public void testJsonSerialisation() BaseComponent[] parsed = ComponentSerializer.parse( jsonString ); assertEquals( "Test string with a placeholder", BaseComponent.toPlainText( parsed ) ); - assertEquals( "Test string with " + WHITE + "a placeholder", BaseComponent.toLegacyText( parsed ) ); + assertEquals( "Test string with a placeholder", BaseComponent.toLegacyText( parsed ) ); } @Test public void testTranslateComponent() { TranslatableComponent item = new TranslatableComponent( "item.swordGold.name" ); - item.setColor( AQUA ); TranslatableComponent component = new TranslatableComponent( "commands.give.success", item, "5", "thinkofdeath" ); assertEquals( "Given Golden Sword * 5 to thinkofdeath", component.toPlainText() ); - assertEquals( "Given " + AQUA + "Golden Sword * " + WHITE + "5 to " + WHITE + "thinkofdeath", component.toLegacyText() ); + component.setColor( RED ); + assertEquals( RED + "Given Golden Sword * 5 to thinkofdeath", component.toLegacyText() ); + item.setColor( AQUA ); + assertEquals( RED + "Given " + AQUA + "Golden Sword" + RED + " * 5 to thinkofdeath", component.toLegacyText() ); + component.setColor( null ); + assertEquals( "Given " + AQUA + "Golden Sword" + RESET + " * 5 to thinkofdeath", component.toLegacyText() ); BaseComponent legacyColorTest = new ComponentBuilder( "Test " ).color( RED ).append( component ).build(); - assertEquals( RED + "Test " + RED + "Given " + AQUA + "Golden Sword" + RED + " * " + RED + "5" + RED + " to " - + RED + "thinkofdeath", legacyColorTest.toLegacyText() ); + assertEquals( RED + "Test Given " + AQUA + "Golden Sword" + RED + " * 5 to thinkofdeath", legacyColorTest.toLegacyText() ); + + BaseComponent legacyColorTest2 = new TextComponent( "Test " ); + legacyColorTest2.addExtra( new ComponentBuilder( "abc " ).color( GRAY ).build() ); + legacyColorTest2.addExtra( component ); + legacyColorTest2.addExtra( new ComponentBuilder( " def" ).build() ); + assertEquals( "Test " + GRAY + "abc " + RED + "Given " + AQUA + "Golden Sword" + RED + " * 5 to thinkofdeath" + RESET + " def", legacyColorTest2.toLegacyText() ); + legacyColorTest2.setColor( RED ); + assertEquals( RED + "Test " + GRAY + "abc " + RED + "Given " + AQUA + "Golden Sword" + RED + " * 5 to thinkofdeath def", legacyColorTest2.toLegacyText() ); TranslatableComponent positional = new TranslatableComponent( "book.pageIndicator", "5", "50" ); assertEquals( "Page 5 of 50", positional.toPlainText() ); - assertEquals( "Page " + WHITE + "5 of " + WHITE + "50", positional.toLegacyText() ); + assertEquals( "Page 5 of 50", positional.toLegacyText() ); TranslatableComponent one_four_two = new TranslatableComponent( "filled_map.buried_treasure" ); assertEquals( "Buried Treasure Map", one_four_two.toPlainText() );