From c84d6f00355f2207f054757d457038bad60842a8 Mon Sep 17 00:00:00 2001 From: md_5 Date: Fri, 1 Nov 2013 17:14:18 +1100 Subject: [PATCH] Add really efficient text -> json translation. Doesn't support format codes yet. --- .../java/net/md_5/bungee/api/ChatColor.java | 55 +++++---- .../java/net/md_5/bungee/UserConnection.java | 7 +- proxy/src/main/java/net/md_5/bungee/Util.java | 55 +++++++-- .../net/md_5/bungee/util/TextWrapper.java | 110 ------------------ 4 files changed, 76 insertions(+), 151 deletions(-) delete mode 100644 proxy/src/main/java/net/md_5/bungee/util/TextWrapper.java diff --git a/api/src/main/java/net/md_5/bungee/api/ChatColor.java b/api/src/main/java/net/md_5/bungee/api/ChatColor.java index 0df1cd5e2..2de614710 100644 --- a/api/src/main/java/net/md_5/bungee/api/ChatColor.java +++ b/api/src/main/java/net/md_5/bungee/api/ChatColor.java @@ -3,6 +3,7 @@ package net.md_5.bungee.api; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; +import lombok.Getter; /** * Simplistic enumeration of all supported color values for chat. @@ -13,100 +14,101 @@ public enum ChatColor /** * Represents black. */ - BLACK( '0' ), + BLACK( '0', "black" ), /** * Represents dark blue. */ - DARK_BLUE( '1' ), + DARK_BLUE( '1', "dark_blue" ), /** * Represents dark green. */ - DARK_GREEN( '2' ), + DARK_GREEN( '2', "dark_green" ), /** * Represents dark blue (aqua). */ - DARK_AQUA( '3' ), + DARK_AQUA( '3', "dark_aqua" ), /** * Represents dark red. */ - DARK_RED( '4' ), + DARK_RED( '4', "dark_red" ), /** * Represents dark purple. */ - DARK_PURPLE( '5' ), + DARK_PURPLE( '5', "dark_purple" ), /** * Represents gold. */ - GOLD( '6' ), + GOLD( '6', "gold" ), /** * Represents gray. */ - GRAY( '7' ), + GRAY( '7', "gray" ), /** * Represents dark gray. */ - DARK_GRAY( '8' ), + DARK_GRAY( '8', "dark_gray" ), /** * Represents blue. */ - BLUE( '9' ), + BLUE( '9', "blue" ), /** * Represents green. */ - GREEN( 'a' ), + GREEN( 'a', "green" ), /** * Represents aqua. */ - AQUA( 'b' ), + AQUA( 'b', "aqua" ), /** * Represents red. */ - RED( 'c' ), + RED( 'c', "red" ), /** * Represents light purple. */ - LIGHT_PURPLE( 'd' ), + LIGHT_PURPLE( 'd', "light_purple" ), /** * Represents yellow. */ - YELLOW( 'e' ), + YELLOW( 'e', "yellow" ), /** * Represents white. */ - WHITE( 'f' ), + WHITE( 'f', "white" ), /** * Represents magical characters that change around randomly. */ - MAGIC( 'k' ), + MAGIC( 'k', "obfuscated" ), /** * Makes the text bold. */ - BOLD( 'l' ), + BOLD( 'l', "bold" ), /** * Makes a line appear through the text. */ - STRIKETHROUGH( 'm' ), + STRIKETHROUGH( 'm', "strikethrough" ), /** * Makes the text appear underlined. */ - UNDERLINE( 'n' ), + UNDERLINE( 'n', "underline" ), /** * Makes the text italic. */ - ITALIC( 'o' ), + ITALIC( 'o', "italic" ), /** * Resets all previous chat colors or formats. */ - RESET( 'r' ); + RESET( 'r', "reset" ); /** * The special character which prefixes all chat colour codes. Use this if * you need to dynamically convert colour codes from your custom format. */ public static final char COLOR_CHAR = '\u00A7'; + public static final String ALL_CODES = "0123456789AaBbCcDdEeFfKkLlMmNnOoRr"; /** * Pattern to remove all colour codes. */ - private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile( "(?i)" + String.valueOf( COLOR_CHAR ) + "[0-9A-FK-OR]" ); + public static final Pattern STRIP_COLOR_PATTERN = Pattern.compile( "(?i)" + String.valueOf( COLOR_CHAR ) + "[0-9A-FK-OR]" ); /** * Colour instances keyed by their active character. */ @@ -119,6 +121,8 @@ public enum ChatColor * This colour's colour char prefixed by the {@link #COLOR_CHAR}. */ private final String toString; + @Getter + private final String name; static { @@ -128,9 +132,10 @@ public enum ChatColor } } - private ChatColor(char code) + private ChatColor(char code, String name) { this.code = code; + this.name = name; this.toString = new String( new char[] { COLOR_CHAR, code @@ -164,7 +169,7 @@ public enum ChatColor char[] b = textToTranslate.toCharArray(); for ( int i = 0; i < b.length - 1; i++ ) { - if ( b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf( b[i + 1] ) > -1 ) + if ( b[i] == altColorChar && ALL_CODES.indexOf( b[i + 1] ) > -1 ) { b[i] = ChatColor.COLOR_CHAR; b[i + 1] = Character.toLowerCase( b[i + 1] ); diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java index ca45e1788..621b23474 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -40,7 +40,6 @@ import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.util.CaseInsensitiveSet; -import net.md_5.bungee.util.TextWrapper; @RequiredArgsConstructor public final class UserConnection implements ProxiedPlayer @@ -275,11 +274,7 @@ public final class UserConnection implements ProxiedPlayer @Override public void sendMessage(String message) { - // TODO: Fix this - for ( String s : TextWrapper.wrapText( message ) ) - { - unsafe().sendPacket( new Chat( Util.stupify( s ) ) ); - } + unsafe().sendPacket( new Chat( Util.stupify( message ) ) ); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/Util.java b/proxy/src/main/java/net/md_5/bungee/Util.java index cd8b6df27..85b7c1ff5 100644 --- a/proxy/src/main/java/net/md_5/bungee/Util.java +++ b/proxy/src/main/java/net/md_5/bungee/Util.java @@ -1,7 +1,12 @@ package net.md_5.bungee; +import com.google.common.base.Joiner; +import com.google.gson.Gson; +import com.google.gson.JsonObject; import java.net.InetSocketAddress; -import java.util.Collection; +import java.util.ArrayList; +import java.util.List; +import net.md_5.bungee.api.ChatColor; /** * Series of utility classes to perform various operations. @@ -61,19 +66,49 @@ public class Util public static String format(Iterable objects, String separators) { - StringBuilder ret = new StringBuilder(); - for ( Object o : objects ) - { - ret.append( o ); - ret.append( separators ); - } + return Joiner.on( separators ).join( objects ); + } - return ( ret.length() == 0 ) ? "" : ret.substring( 0, ret.length() - separators.length() ); + public static void main(String[] args) + { + System.out.println( stupify( "§5H§6E§7L" ) ); } public static String stupify(String text) { - // TODO: Colour text wrapper to work around 1.7 client bug with section sign - return "{\"text\":" + BungeeCord.getInstance().gson.toJson( text ) + "}"; + List sections = new ArrayList<>(); + char[] c = text.toCharArray(); + + char currentChar = 0x00; + StringBuilder buffer = new StringBuilder(); + + for ( int i = 0; i < text.length(); i++ ) + { + if ( c[i] == ChatColor.COLOR_CHAR && ChatColor.ALL_CODES.indexOf( c[i + 1] ) != -1 ) + { + sections.add( generateAndReset( currentChar, buffer ) ); + currentChar = Character.toLowerCase( c[++i] ); + } else + { + buffer.append( c[i] ); + } + } + sections.add( generateAndReset( currentChar, buffer ) ); + + return new Gson().toJson( sections ); + } + + private static JsonObject generateAndReset(char currentChar, StringBuilder buffer) + { + JsonObject entry = new JsonObject(); + ChatColor colour = ChatColor.getByChar( currentChar ); + if ( colour != null ) + { + entry.addProperty( "color", colour.getName() ); + } + entry.addProperty( "text", buffer.toString() ); + + buffer.setLength( 0 ); + return entry; } } diff --git a/proxy/src/main/java/net/md_5/bungee/util/TextWrapper.java b/proxy/src/main/java/net/md_5/bungee/util/TextWrapper.java deleted file mode 100644 index ab770a224..000000000 --- a/proxy/src/main/java/net/md_5/bungee/util/TextWrapper.java +++ /dev/null @@ -1,110 +0,0 @@ -package net.md_5.bungee.util; - -public class TextWrapper -{ - - private static final int[] characterWidths = new int[] - { - 1, 9, 9, 8, 8, 8, 8, 7, 9, 8, 9, 9, 8, 9, 9, 9, - 8, 8, 8, 8, 9, 9, 8, 9, 8, 8, 8, 8, 8, 9, 9, 9, - 4, 2, 5, 6, 6, 6, 6, 3, 5, 5, 5, 6, 2, 6, 2, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 5, 6, 5, 6, - 7, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 4, 6, 6, - 3, 6, 6, 6, 6, 6, 5, 6, 6, 2, 6, 5, 3, 6, 6, 6, - 6, 6, 6, 6, 4, 6, 6, 6, 6, 6, 6, 5, 2, 5, 7, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 3, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, - 6, 3, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 2, 6, 6, - 8, 9, 9, 6, 6, 6, 8, 8, 6, 8, 8, 8, 8, 8, 6, 6, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 6, 9, 9, 9, 5, 9, 9, - 8, 7, 7, 8, 7, 8, 8, 8, 7, 8, 8, 7, 9, 9, 6, 7, - 7, 7, 7, 7, 9, 6, 7, 8, 7, 6, 6, 9, 7, 6, 7, 1 - }; - private static final char COLOR_CHAR = '\u00A7'; - private static final int CHAT_WINDOW_WIDTH = 320; - private static final int CHAT_STRING_LENGTH = 119; - private static final String allowedChars - = " !\"#$%&'()*+,-./\n" - + "0123456789:;<=>?\n" - + "@ABCDEFGHIJKLMNO\n" - + "PQRSTUVWXYZ[\\]^_\n" - + "'abcdefghijklmno\n" - + "pqrstuvwxyz{|}~⌂\n" - + "ÇüéâäàåçêëèïîìÄÅ\n" - + "ÉæÆôöòûùÿÖÜø£Ø׃\n" - + "áíóúñѪº¿®¬½¼¡«»"; - - public static String[] wrapText(final String text) - { - final StringBuilder out = new StringBuilder(); - char colorChar = 'f'; - int lineWidth = 0; - int lineLength = 0; - - // Go over the message char by char. - for ( int i = 0; i < text.length(); i++ ) - { - char ch = text.charAt( i ); - - // Get the color - if ( ch == COLOR_CHAR && i < text.length() - 1 ) - { - // We might need a linebreak ... so ugly ;( - if ( lineLength + 2 > CHAT_STRING_LENGTH ) - { - out.append( '\n' ); - lineLength = 0; - if ( colorChar != 'f' && colorChar != 'F' ) - { - out.append( COLOR_CHAR ).append( colorChar ); - lineLength += 2; - } - } - colorChar = text.charAt( ++i ); - out.append( COLOR_CHAR ).append( colorChar ); - lineLength += 2; - continue; - } - - // Figure out if it's allowed - int index = allowedChars.indexOf( ch ); - if ( index == -1 ) - { - // Invalid character .. skip it. - continue; - } else - { - // Sadly needed as the allowedChars string misses the first - index += 32; - } - - // Find the width - final int width = characterWidths[index]; - - // See if we need a linebreak - if ( lineLength + 1 > CHAT_STRING_LENGTH || lineWidth + width >= CHAT_WINDOW_WIDTH ) - { - out.append( '\n' ); - lineLength = 0; - - // Re-apply the last color if it isn't the default - if ( colorChar != 'f' && colorChar != 'F' ) - { - out.append( COLOR_CHAR ).append( colorChar ); - lineLength += 2; - } - lineWidth = width; - } else - { - lineWidth += width; - } - out.append( ch ); - lineLength++; - } - - // Return it split - return out.toString().split( "\n" ); - } -}