diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index 3d4db7104..1ea487819 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -488,7 +488,7 @@ public class BungeeCord extends ProxyServer { getConsole().sendMessage( message ); // TODO: Here too - broadcast( new Chat( Util.stupify( message ) ) ); + broadcast( new Chat( ChatConverter.toJSONChat( message ) ) ); } public void addConnection(UserConnection con) diff --git a/proxy/src/main/java/net/md_5/bungee/ChatConverter.java b/proxy/src/main/java/net/md_5/bungee/ChatConverter.java new file mode 100644 index 000000000..108dfefb4 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/ChatConverter.java @@ -0,0 +1,178 @@ +package net.md_5.bungee; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ChatConverter { + + private static final Gson gson = new Gson(); + private static final char COLOR_CHAR = '\u00A7'; + private static final Pattern url = Pattern.compile("^(?:(https?)://)?([-\\w_\\.]{2,}\\.[a-z]{2,4})(/\\S*)?$"); + + public static String toJSONChat(String txt) { + Message msg = new Message(); + ArrayList parts = new ArrayList(); + StringBuilder buf = new StringBuilder(); + Matcher matcher = url.matcher(txt); + for (int i = 0; i < txt.length(); i++) { + char c = txt.charAt(i); + if (c != COLOR_CHAR) { + int pos = txt.indexOf(' ', i); + if (pos == -1) pos = txt.length(); + if (matcher.region(i, pos).find()) { //Web link handling + msg.text = buf.toString(); + buf = new StringBuilder(); + parts.add(msg); + Message old = msg; + msg = new Message(old); + msg.clickEvent = new ClickEvent(); + msg.clickEvent.action = "open_url"; + String urlString = txt.substring(i, pos); + if (urlString.startsWith("http")) { + msg.text = msg.clickEvent.value = urlString; + } else { + msg.text = urlString; + msg.clickEvent.value = "http://" + urlString; + } + parts.add(msg); + i += pos - i - 1; + msg = new Message(old); + continue; + } + buf.append(c); + continue; + } + i++; + c = txt.charAt(i); + if (c >= 'A' && c <= 'Z') { + c += 32; + } + msg.text = buf.toString(); + buf = new StringBuilder(); + parts.add(msg); + msg = new Message(msg); + switch(c) { + case 'k': + msg.obfuscated = true; + break; + case 'l': + msg.bold = true; + break; + case 'm': + msg.strikethrough = true; + break; + case 'n': + msg.underlined = true; + break; + case 'o': + msg.italic = true; + break; + default: + msg.obfuscated = false; + msg.bold = false; + msg.strikethrough = false; + msg.underlined = false; + msg.italic = false; + if (c != 'r') { + msg.color = Color.fromCode(Character.toString(c)); + } else { + msg.color = Color.WHITE; + } + break; + } + } + msg.text = buf.toString(); + parts.add(msg); + return gson.toJson(parts); + } +} + +class Message { + public String text; + + public boolean bold; + public boolean italic; + public boolean underlined; + public boolean strikethrough; + public boolean obfuscated; + + public Color color; + + public ClickEvent clickEvent; + + public Message() { + + } + + public Message(Message old) { + this.bold = old.bold; + this.italic = old.italic; + this.underlined = old.underlined; + this.strikethrough = old.strikethrough; + this.color = old.color; + } +} + +class ClickEvent { + public String action; + public String value; +} + +enum Color { + @SerializedName("black") + BLACK("0"), + @SerializedName("dark_blue") + DARK_BLUE("1"), + @SerializedName("dark_green") + DARK_GREEN("2"), + @SerializedName("dark_aqua") + DARK_AQUA("3"), + @SerializedName("dark_red") + DARK_RED("4"), + @SerializedName("dark_purple") + DARK_PURPLE("5"), + @SerializedName("gold") + GOLD("6"), + @SerializedName("gray") + GRAY("7"), + @SerializedName("dark_gray") + DARK_GRAY("8"), + @SerializedName("blue") + BLUE("9"), + @SerializedName("green") + GREEN("a"), + @SerializedName("aqua") + AQUA("b"), + @SerializedName("red") + RED("c"), + @SerializedName("light_purple") + LIGHT_PURPLE("d"), + @SerializedName("yellow") + YELLOW("e"), + @SerializedName("white") + WHITE("f"); + + public String code; + + Color(String code) { + this.code = code; + } + + + private static HashMap codeMap = new HashMap(); + + public static Color fromCode(String code) { + return codeMap.get(code); + } + + static { + for (Color color : values()) { + codeMap.put(color.code, color); + } + } +} 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 a928476e0..ae16163ba 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -256,7 +256,7 @@ public final class UserConnection implements ProxiedPlayer @Override public synchronized void disconnect(String reason) { - disconnect0( Util.stupify( reason ) ); + disconnect0( ChatConverter.toJSONChat( reason ) ); } public synchronized void disconnect0(String reason) @@ -283,7 +283,7 @@ public final class UserConnection implements ProxiedPlayer @Override public void sendMessage(String message) { - unsafe().sendPacket( new Chat( Util.stupify( message ) ) ); + unsafe().sendPacket( new Chat( ChatConverter.toJSONChat( 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 15027826f..a68f8da8f 100644 --- a/proxy/src/main/java/net/md_5/bungee/Util.java +++ b/proxy/src/main/java/net/md_5/bungee/Util.java @@ -68,42 +68,4 @@ public class Util { return Joiner.on( separators ).join( objects ); } - - public static String stupify(String 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 BungeeCord.getInstance().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/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index 473fc0a5a..8ddcd6289 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -397,7 +397,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection { if ( !ch.isClosed() ) { - unsafe().sendPacket( new Kick( Util.stupify( reason ) ) ); + unsafe().sendPacket( new Kick( ChatConverter.toJSONChat( reason ) ) ); ch.close(); } }