diff --git a/api/src/main/java/com/velocitypowered/api/proxy/Player.java b/api/src/main/java/com/velocitypowered/api/proxy/Player.java index 51d966044..71f6d6006 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -275,4 +275,11 @@ public interface Player extends CommandSource, Identified, InboundConnection, */ @Override boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data); + + /** + * Gets the player's client brand. + * + * @return the player's client brand + */ + Optional getClientBrand(); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index e26814244..6d4e735f8 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -230,6 +230,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { player.getKnownChannels().removeAll(PluginMessageUtil.getChannels(packet)); backendConn.write(packet.retain()); } else if (PluginMessageUtil.isMcBrand(packet)) { + player.setClientBrand(PluginMessageUtil.readBrandMessage(packet.content())); backendConn.write(PluginMessageUtil .rewriteMinecraftBrand(packet, server.getVersion(), player.getProtocolVersion())); } else if (BungeeCordMessageResponder.isBungeeCordMessage(packet)) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java index 64bb15122..387b721da 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ConnectedPlayer.java @@ -142,6 +142,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { private final Queue outstandingResourcePacks = new ArrayDeque<>(); private @Nullable ResourcePackInfo pendingResourcePack; private @Nullable ResourcePackInfo appliedResourcePack; + private @Nullable String clientBrand; ConnectedPlayer(VelocityServer server, GameProfile profile, MinecraftConnection connection, @Nullable InetSocketAddress virtualHost, boolean onlineMode) { @@ -871,6 +872,15 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { return true; } + @Override + public Optional getClientBrand() { + return Optional.ofNullable(clientBrand); + } + + void setClientBrand(String clientBrand) { + this.clientBrand = clientBrand; + } + @Override public void spoofChatInput(String input) { Preconditions.checkArgument(input.length() <= Chat.MAX_SERVERBOUND_MESSAGE_LENGTH, diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/util/PluginMessageUtil.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/util/PluginMessageUtil.java index 5e30c1352..4847a2b6a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/util/PluginMessageUtil.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/util/PluginMessageUtil.java @@ -160,11 +160,15 @@ public final class PluginMessageUtil { return new PluginMessage(message.getChannel(), rewrittenBuf); } - private static String readBrandMessage(ByteBuf content) { - // Some clients (mostly poorly-implemented bots) do not send validly-formed brand messages. - // In order to accommodate their broken behavior, we'll first try to read in the 1.8 format, and - // if that fails, treat it as a 1.7-format message (which has no prefixed length). (The message - // Velocity sends will be in the correct format depending on the protocol.) + /** + * Some clients (mostly poorly-implemented bots) do not send validly-formed brand messages. + * In order to accommodate their broken behavior, we'll first try to read in the 1.8 format, and + * if that fails, treat it as a 1.7-format message (which has no prefixed length). (The message + * Velocity sends will be in the correct format depending on the protocol.) + * @param content the brand packet + * @return the client brand + */ + public static String readBrandMessage(ByteBuf content) { try { return ProtocolUtils.readString(content.slice()); } catch (Exception e) {