diff --git a/api/src/main/java/net/md_5/bungee/api/CommandSender.java b/api/src/main/java/net/md_5/bungee/api/CommandSender.java index 061f889f0..962489351 100644 --- a/api/src/main/java/net/md_5/bungee/api/CommandSender.java +++ b/api/src/main/java/net/md_5/bungee/api/CommandSender.java @@ -19,6 +19,7 @@ public interface CommandSender * * @param message the message to send */ + @Deprecated public void sendMessage(String message); /** @@ -27,6 +28,7 @@ public interface CommandSender * * @param messages the messages to send */ + @Deprecated public void sendMessages(String... messages); /** diff --git a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java index bc7bf2c3b..06155010c 100644 --- a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java +++ b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java @@ -232,6 +232,7 @@ public abstract class ProxyServer * * @param message the message to broadcast */ + @Deprecated public abstract void broadcast(String message); /** diff --git a/api/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java b/api/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java index 3a52cf132..8651071ec 100644 --- a/api/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java +++ b/api/src/main/java/net/md_5/bungee/api/chat/BaseComponent.java @@ -49,6 +49,22 @@ public abstract class BaseComponent { setObfuscated(old.isObfuscatedRaw()); } + public static String toLegacyText(BaseComponent[] components) { + StringBuilder builder = new StringBuilder(); + for (BaseComponent msg : components) { + builder.append(msg.toLegacyText()); + } + return builder.toString(); + } + + public static String toPlainText(BaseComponent[] components) { + StringBuilder builder = new StringBuilder(); + for (BaseComponent msg : components) { + builder.append(msg.toPlainText()); + } + return builder.toString(); + } + /** * Returns the color of this component. This uses the parent's color diff --git a/api/src/main/java/net/md_5/bungee/api/chat/TextComponent.java b/api/src/main/java/net/md_5/bungee/api/chat/TextComponent.java index 6ec8da9e2..d398f7b3a 100644 --- a/api/src/main/java/net/md_5/bungee/api/chat/TextComponent.java +++ b/api/src/main/java/net/md_5/bungee/api/chat/TextComponent.java @@ -6,11 +6,104 @@ import lombok.NoArgsConstructor; import lombok.Setter; import net.md_5.bungee.api.ChatColor; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + @Getter @Setter @AllArgsConstructor @NoArgsConstructor public class TextComponent extends BaseComponent { + + private static final Pattern url = Pattern.compile("^(?:(https?)://)?([-\\w_\\.]{2,}\\.[a-z]{2,4})(/\\S*)?$"); + + public static BaseComponent[] fromLegacyText(String message) { + ArrayList components = new ArrayList<>(); + StringBuilder builder = new StringBuilder(); + TextComponent component = new TextComponent(); + Matcher matcher = url.matcher(message); + + for ( int i = 0; i < message.length(); i++ ) { + char c = message.charAt(i); + if (c == ChatColor.COLOR_CHAR) { + i++; + c = message.charAt(i); + if (c >= 'A' && c <= 'Z') { + c += 32; + } + if (builder.length() > 0) { + TextComponent old = component; + component = new TextComponent(old); + old.setText(builder.toString()); + builder = new StringBuilder(); + components.add(old); + } + ChatColor format = ChatColor.getByChar(c); + switch (format) { + case BOLD: + component.setBold(true); + break; + case ITALIC: + component.setItalic(true); + break; + case UNDERLINE: + component.setUnderlined(true); + break; + case STRIKETHROUGH: + component.setStrikethrough(true); + break; + case MAGIC: + component.setObfuscated(true); + break; + case RESET: + format = ChatColor.WHITE; + default: + component = new TextComponent(); + component.setColor(format); + break; + } + continue; + } + int pos = message.indexOf(' ', i); + if (pos == -1) pos = message.length(); + if (matcher.region(i, pos).find()) { //Web link handling + + if (builder.length() > 0) { + TextComponent old = component; + component = new TextComponent(old); + old.setText(builder.toString()); + builder = new StringBuilder(); + components.add(old); + } + + TextComponent old = component; + component = new TextComponent(old); + ClickEvent clickEvent = new ClickEvent(); + clickEvent.setAction(ClickEvent.Action.OPEN_URL); + String urlString = message.substring(i, pos); + if (urlString.startsWith("http")) { + component.setText(urlString); + clickEvent.setValue(urlString); + } else { + component.setText(urlString); + clickEvent.setValue("http://" + urlString); + } + component.setClickEvent(clickEvent); + components.add(component); + i += pos - i - 1; + component = old; + continue; + } + builder.append(c); + } + if (builder.length() > 0) { + component.setText(builder.toString()); + components.add(component); + } + return components.toArray(new BaseComponent[components.size()]); + } + private String text; public TextComponent(TextComponent old) { diff --git a/api/src/main/java/net/md_5/bungee/api/connection/Connection.java b/api/src/main/java/net/md_5/bungee/api/connection/Connection.java index 2c9cae140..fb1461644 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/Connection.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/Connection.java @@ -1,6 +1,8 @@ package net.md_5.bungee.api.connection; import java.net.InetSocketAddress; + +import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.protocol.DefinedPacket; /** @@ -26,8 +28,29 @@ public interface Connection * @param reason the reason shown to the player / sent to the server on * disconnect */ + @Deprecated void disconnect(String reason); + /** + * Disconnects this end of the connection for the specified reason. If this + * is an {@link ProxiedPlayer} the respective server connection will be + * closed too. + * + * @param reason the reason shown to the player / sent to the server on + * disconnect + */ + void disconnect(BaseComponent[] reason); + + /** + * Disconnects this end of the connection for the specified reason. If this + * is an {@link ProxiedPlayer} the respective server connection will be + * closed too. + * + * @param reason the reason shown to the player / sent to the server on + * disconnect + */ + void disconnect(BaseComponent reason); + /** * Get the unsafe methods of this class. * diff --git a/api/src/main/java/net/md_5/bungee/api/event/ServerKickEvent.java b/api/src/main/java/net/md_5/bungee/api/event/ServerKickEvent.java index 50a4cc933..7df8d9695 100644 --- a/api/src/main/java/net/md_5/bungee/api/event/ServerKickEvent.java +++ b/api/src/main/java/net/md_5/bungee/api/event/ServerKickEvent.java @@ -3,6 +3,8 @@ package net.md_5.bungee.api.event; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.plugin.Cancellable; @@ -28,7 +30,7 @@ public class ServerKickEvent extends Event implements Cancellable /** * Kick reason. */ - private String kickReason; + private BaseComponent[] kickReasonComponent; /** * Server to send player to if this event is cancelled. */ @@ -44,16 +46,26 @@ public class ServerKickEvent extends Event implements Cancellable CONNECTING, CONNECTED, UNKNOWN; } - public ServerKickEvent(ProxiedPlayer player, String kickReason, ServerInfo cancelServer) + public ServerKickEvent(ProxiedPlayer player, BaseComponent[] kickReasonComponent, ServerInfo cancelServer) { - this( player, kickReason, cancelServer, State.UNKNOWN ); + this( player, kickReasonComponent, cancelServer, State.UNKNOWN ); } - public ServerKickEvent(ProxiedPlayer player, String kickReason, ServerInfo cancelServer, State state) + public ServerKickEvent(ProxiedPlayer player, BaseComponent[] kickReasonComponent, ServerInfo cancelServer, State state) { this.player = player; - this.kickReason = kickReason; + this.kickReasonComponent = kickReasonComponent; this.cancelServer = cancelServer; this.state = state; } + + @Deprecated + public String getKickReason() { + return BaseComponent.toLegacyText(kickReasonComponent); + } + + @Deprecated + public void setKickReason(String reason) { + kickReasonComponent = TextComponent.fromLegacyText(reason); + } } 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 67c8f93fe..80ca6ee9c 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -2,6 +2,7 @@ package net.md_5.bungee; import com.google.common.io.ByteStreams; import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.log.BungeeLogger; import net.md_5.bungee.reconnect.YamlReconnectHandler; @@ -489,17 +490,13 @@ public class BungeeCord extends ProxyServer public void broadcast(String message) { getConsole().sendMessage( message ); - broadcast(ComponentSerializer.fromLegacyChat(message)); + broadcast(TextComponent.fromLegacyText(message)); } @Override public void broadcast(BaseComponent[] message) { - StringBuilder constr = new StringBuilder(); - for (BaseComponent msg : message) { - constr.append( msg.toLegacyText() ); - } - getConsole().sendMessage( constr.toString() ); - broadcast( new Chat(ComponentSerializer.toString(message)) ); + getConsole().sendMessage(BaseComponent.toLegacyText(message)); + broadcast(new Chat(ComponentSerializer.toString(message))); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java index b5c5af500..f1490c64a 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -5,7 +5,10 @@ import java.util.concurrent.TimeUnit; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.connection.Server; +import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.packet.PluginMessage; @@ -40,10 +43,15 @@ public class ServerConnection implements Server @Override public synchronized void disconnect(String reason) { + disconnect( TextComponent.fromLegacyText(reason) ); + } + + @Override + public void disconnect(BaseComponent[] reason) { if ( !ch.isClosed() ) { // TODO: Can we just use a future here? - unsafe().sendPacket( new Kick( reason ) ); + unsafe().sendPacket( new Kick(ComponentSerializer.toString(reason) ) ); ch.getHandle().eventLoop().schedule( new Runnable() { @Override @@ -53,6 +61,12 @@ public class ServerConnection implements Server } }, 100, TimeUnit.MILLISECONDS ); } + + } + + @Override + public void disconnect(BaseComponent reason) { + disconnect(new BaseComponent[]{reason}); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java index f3c3e93f4..0d317c935 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -15,6 +15,7 @@ import net.md_5.bungee.api.event.ServerSwitchEvent; import net.md_5.bungee.api.score.Objective; import net.md_5.bungee.api.score.Scoreboard; import net.md_5.bungee.api.score.Team; +import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.connection.CancelSendSignal; import net.md_5.bungee.connection.DownstreamBridge; import net.md_5.bungee.netty.HandlerBoss; @@ -211,7 +212,7 @@ public class ServerConnector extends PacketHandler { def = null; } - ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( user, kick.getMessage(), def, ServerKickEvent.State.CONNECTING ) ); + ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( user, ComponentSerializer.parse(kick.getMessage()), def, ServerKickEvent.State.CONNECTING ) ); if ( event.isCancelled() && event.getCancelServer() != null ) { user.connect( event.getCancelServer() ); 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 af5ee9121..85d3adb10 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -21,6 +21,7 @@ import lombok.RequiredArgsConstructor; import lombok.Setter; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PermissionCheckEvent; @@ -258,15 +259,25 @@ public final class UserConnection implements ProxiedPlayer @Override public synchronized void disconnect(String reason) { - disconnect0( ComponentSerializer.toString( ComponentSerializer.fromLegacyChat( reason ) ) ); + disconnect0( TextComponent.fromLegacyText(reason) ); } - public synchronized void disconnect0(String reason) + @Override + public void disconnect(BaseComponent[] reason) { + disconnect0( reason ); + } + + @Override + public void disconnect(BaseComponent reason) { + disconnect0(new BaseComponent[]{reason}); + } + + public synchronized void disconnect0(BaseComponent[] reason) { if ( ch.getHandle().isActive() ) { - bungee.getLogger().log( Level.INFO, "[" + getName() + "] disconnected with: " + reason ); - unsafe().sendPacket( new Kick( reason ) ); + bungee.getLogger().log( Level.INFO, "[" + getName() + "] disconnected with: " + BaseComponent.toLegacyText(reason) ); + unsafe().sendPacket( new Kick( ComponentSerializer.toString(reason) ) ); ch.close(); if ( server != null ) { @@ -285,7 +296,7 @@ public final class UserConnection implements ProxiedPlayer @Override public void sendMessage(String message) { - sendMessage(ComponentSerializer.fromLegacyChat(message)); + sendMessage(TextComponent.fromLegacyText(message)); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java b/proxy/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java index 7dd90c0a5..3dc4fe79f 100644 --- a/proxy/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java +++ b/proxy/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java @@ -25,8 +25,6 @@ public class ComponentSerializer implements JsonSerializer, JsonD registerTypeAdapter(TranslatableComponent.class, new TranslatableComponentSerializer()). create(); - private static final Pattern url = Pattern.compile("^(?:(https?)://)?([-\\w_\\.]{2,}\\.[a-z]{2,4})(/\\S*)?$"); - public static BaseComponent[] parse(String json) { if (json.startsWith("[")) { //Array return gson.fromJson(json, BaseComponent[].class); @@ -42,92 +40,6 @@ public class ComponentSerializer implements JsonSerializer, JsonD return gson.toJson(components); } - public static BaseComponent[] fromLegacyChat(String message) { - ArrayList components = new ArrayList<>(); - StringBuilder builder = new StringBuilder(); - TextComponent component = new TextComponent(); - Matcher matcher = url.matcher(message); - - for ( int i = 0; i < message.length(); i++ ) { - char c = message.charAt(i); - if (c == ChatColor.COLOR_CHAR) { - i++; - c = message.charAt(i); - if (c >= 'A' && c <= 'Z') { - c += 32; - } - if (builder.length() > 0) { - TextComponent old = component; - component = new TextComponent(old); - old.setText(builder.toString()); - builder = new StringBuilder(); - components.add(old); - } - ChatColor format = ChatColor.getByChar(c); - switch (format) { - case BOLD: - component.setBold(true); - break; - case ITALIC: - component.setItalic(true); - break; - case UNDERLINE: - component.setUnderlined(true); - break; - case STRIKETHROUGH: - component.setStrikethrough(true); - break; - case MAGIC: - component.setObfuscated(true); - break; - case RESET: - format = ChatColor.WHITE; - default: - component = new TextComponent(); - component.setColor(format); - break; - } - continue; - } - int pos = message.indexOf(' ', i); - if (pos == -1) pos = message.length(); - if (matcher.region(i, pos).find()) { //Web link handling - - if (builder.length() > 0) { - TextComponent old = component; - component = new TextComponent(old); - old.setText(builder.toString()); - builder = new StringBuilder(); - components.add(old); - } - - TextComponent old = component; - component = new TextComponent(old); - ClickEvent clickEvent = new ClickEvent(); - clickEvent.setAction(ClickEvent.Action.OPEN_URL); - String urlString = message.substring(i, pos); - if (urlString.startsWith("http")) { - component.setText(urlString); - clickEvent.setValue(urlString); - } else { - component.setText(urlString); - clickEvent.setValue("http://" + urlString); - } - component.setClickEvent(clickEvent); - components.add(component); - i += pos - i - 1; - component = old; - continue; - } - builder.append(c); - } - if (builder.length() > 0) { - component.setText(builder.toString()); - components.add(component); - } - return components.toArray(new BaseComponent[components.size()]); - } - @Override public BaseComponent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json.isJsonPrimitive()) { diff --git a/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java b/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java index 3cce5a38d..42a11eb37 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java +++ b/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java @@ -37,11 +37,7 @@ public class ConsoleCommandSender implements CommandSender @Override public void sendMessage(BaseComponent[] message) { - StringBuilder constr = new StringBuilder(); - for (BaseComponent msg : message) { - constr.append( msg.toLegacyText() ); - } - sendMessage( constr.toString() ); + sendMessage(BaseComponent.toLegacyText(message)); } @Override diff --git a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java index 3ab315304..93c6f325f 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java @@ -22,6 +22,7 @@ import net.md_5.bungee.api.score.Position; import net.md_5.bungee.api.score.Score; import net.md_5.bungee.api.score.Scoreboard; import net.md_5.bungee.api.score.Team; +import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.protocol.PacketWrapper; @@ -357,13 +358,13 @@ public class DownstreamBridge extends PacketHandler { def = null; } - ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( con, kick.getMessage(), def, ServerKickEvent.State.CONNECTED ) ); + ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( con, ComponentSerializer.parse(kick.getMessage()), def, ServerKickEvent.State.CONNECTED ) ); if ( event.isCancelled() && event.getCancelServer() != null ) { con.connectNow( event.getCancelServer() ); } else { - con.disconnect0( event.getKickReason() ); // TODO: Json concat util method // TODO: Prefix our own stuff. + con.disconnect0( event.getKickReasonComponent() ); // TODO: Prefix our own stuff. } server.setObsolete( true ); throw new CancelSendSignal(); 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 a5cb8bb23..52179ea56 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 @@ -16,6 +16,8 @@ import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ServerPing; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.PendingConnection; @@ -398,11 +400,25 @@ public class InitialHandler extends PacketHandler implements PendingConnection { if ( !ch.isClosed() ) { - unsafe().sendPacket( new Kick( ComponentSerializer.toString(ComponentSerializer.fromLegacyChat(reason)) ) ); + unsafe().sendPacket( new Kick( ComponentSerializer.toString(TextComponent.fromLegacyText(reason)) ) ); ch.close(); } } + @Override + public void disconnect(BaseComponent[] reason) { + if ( !ch.isClosed() ) + { + unsafe().sendPacket( new Kick( ComponentSerializer.toString(reason) ) ); + ch.close(); + } + } + + @Override + public void disconnect(BaseComponent reason) { + disconnect(new BaseComponent[]{reason}); + } + @Override public String getName() {