From ec32def592fb05407722e7de87994b76007dc90f Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Tue, 11 Jun 2019 02:04:38 -0400 Subject: [PATCH 01/14] Take advantage of pooled ByteBufs in Java cipher ByteBufs are pooled in Velocity, so we can achieve lower memory usage by using what Netty is going to provide to us for free. --- .../encryption/JavaVelocityCipher.java | 58 ++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java b/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java index c7a14815e..88f7fa921 100644 --- a/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java +++ b/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java @@ -2,7 +2,7 @@ package com.velocitypowered.natives.encryption; import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; +import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; import java.security.GeneralSecurityException; import javax.crypto.Cipher; @@ -23,9 +23,6 @@ public class JavaVelocityCipher implements VelocityCipher { return new JavaVelocityCipher(false, key); } }; - private static final int INITIAL_BUFFER_SIZE = 1024 * 8; - private static final ThreadLocal inBufLocal = ThreadLocal.withInitial( - () -> new byte[INITIAL_BUFFER_SIZE]); private final Cipher cipher; private boolean disposed = false; @@ -41,20 +38,12 @@ public class JavaVelocityCipher implements VelocityCipher { ensureNotDisposed(); int inBytes = source.readableBytes(); - ByteBuf asHeapBuf = asHeapBuf(source); + byte[] asBytes = ByteBufUtil.getBytes(source); int outputSize = cipher.getOutputSize(inBytes); - if (!destination.hasArray()) { - byte[] outBuf = new byte[outputSize]; - cipher.update(asHeapBuf.array(), asHeapBuf.arrayOffset(), inBytes, outBuf); - destination.writeBytes(outBuf); - } else { - // If the destination we write to is an array, we can use the backing array directly. - destination.ensureWritable(outputSize); - int produced = cipher.update(asHeapBuf.array(), asHeapBuf.arrayOffset(), inBytes, - destination.array(), destination.arrayOffset()); - destination.writerIndex(destination.writerIndex() + produced); - } + byte[] outBuf = new byte[outputSize]; + cipher.update(asBytes, 0, inBytes, outBuf); + destination.writeBytes(outBuf); } @Override @@ -62,28 +51,31 @@ public class JavaVelocityCipher implements VelocityCipher { ensureNotDisposed(); int inBytes = source.readableBytes(); - ByteBuf asHeapBuf = asHeapBuf(source); - + ByteBuf asHeapBuf = toHeap(source); ByteBuf out = ctx.alloc().heapBuffer(cipher.getOutputSize(inBytes)); - out.writerIndex(cipher.update(asHeapBuf.array(), asHeapBuf.arrayOffset(), inBytes, out.array(), - out.arrayOffset())); - return out; + try { + out.writerIndex( + cipher.update(asHeapBuf.array(), asHeapBuf.arrayOffset() + asHeapBuf.readerIndex(), + inBytes, out.array(), out.arrayOffset() + out.writerIndex())); + return out; + } catch (ShortBufferException e) { + out.release(); + throw e; + } finally { + asHeapBuf.release(); + } } - private static ByteBuf asHeapBuf(ByteBuf source) { - if (source.hasArray()) { - // If this byte buffer is backed by an array, we can just use this buffer directly. - return source; + private static ByteBuf toHeap(ByteBuf src) { + if (!src.isDirect()) { + return src.retain(); } - int inBytes = source.readableBytes(); - byte[] inBuf = inBufLocal.get(); - if (inBuf.length <= inBytes) { - inBuf = new byte[inBytes]; - inBufLocal.set(inBuf); - } - source.readBytes(inBuf, 0, inBytes); - return Unpooled.wrappedBuffer(inBuf, 0, inBytes); + // Copy into a temporary heap buffer. We could use a local buffer, but Netty pools all buffers, + // so we'd lose more than we gain. + ByteBuf asHeapBuf = src.alloc().heapBuffer(src.readableBytes()); + asHeapBuf.writeBytes(src); + return asHeapBuf; } @Override From 5fa5d9567d49f1a17f8314a1f2117f7bf36c9b60 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Tue, 11 Jun 2019 02:05:54 -0400 Subject: [PATCH 02/14] Remove unused NativeConstants --- .../natives/util/NativeConstants.java | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 native/src/main/java/com/velocitypowered/natives/util/NativeConstants.java diff --git a/native/src/main/java/com/velocitypowered/natives/util/NativeConstants.java b/native/src/main/java/com/velocitypowered/natives/util/NativeConstants.java deleted file mode 100644 index f96656125..000000000 --- a/native/src/main/java/com/velocitypowered/natives/util/NativeConstants.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.velocitypowered.natives.util; - -public class NativeConstants { - /** - * The default preferred output buffer size for zlib. - */ - public static final int ZLIB_BUFFER_SIZE = 8192; - - private NativeConstants() { - throw new AssertionError(); - } -} From cc6d060fc5cac874ea37f07605000b684c1ecbad Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Wed, 12 Jun 2019 00:43:30 -0400 Subject: [PATCH 03/14] Clarify error message --- .../proxy/protocol/netty/MinecraftCompressDecoder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftCompressDecoder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftCompressDecoder.java index 56af37e65..358d8154e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftCompressDecoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftCompressDecoder.java @@ -33,7 +33,7 @@ public class MinecraftCompressDecoder extends MessageToMessageDecoder { return; } - checkFrame(expectedSize >= threshold, "Uncompressed size %s is greater than threshold %s", + checkFrame(expectedSize >= threshold, "Uncompressed size %s is less than threshold %s", expectedSize, threshold); checkFrame(expectedSize <= MAXIMUM_UNCOMPRESSED_SIZE, "Expected uncompressed size" + "%s is larger than protocol maximum of %s", expectedSize, MAXIMUM_UNCOMPRESSED_SIZE); From 5c314c9068814aca404b68cf8442af7201bdcf43 Mon Sep 17 00:00:00 2001 From: Gabik21 Date: Mon, 1 Jul 2019 08:54:34 +0200 Subject: [PATCH 04/14] Add 1.7 Protocol Support --- .../api/network/ProtocolVersion.java | 4 +- .../proxy/connection/ConnectionTypes.java | 4 + .../backend/BackendPlaySessionHandler.java | 7 +- .../client/ClientConnectionPhase.java | 3 + .../client/ClientPlaySessionHandler.java | 12 +- .../connection/client/ConnectedPlayer.java | 7 +- .../client/HandshakeSessionHandler.java | 4 + .../client/LoginSessionHandler.java | 3 +- .../LegacyForgeHandshakeBackendPhase.java | 2 +- .../proxy/protocol/ProtocolUtils.java | 98 ++++++++++++- .../proxy/protocol/StateRegistry.java | 55 ++++--- .../proxy/protocol/packet/Chat.java | 4 +- .../proxy/protocol/packet/ClientSettings.java | 11 ++ .../protocol/packet/EncryptionRequest.java | 20 ++- .../protocol/packet/EncryptionResponse.java | 18 ++- .../proxy/protocol/packet/JoinGame.java | 10 +- .../proxy/protocol/packet/KeepAlive.java | 8 +- .../proxy/protocol/packet/PlayerListItem.java | 134 +++++++++++------- .../proxy/protocol/packet/PluginMessage.java | 16 ++- .../protocol/packet/ServerLoginSuccess.java | 7 +- .../protocol/packet/TabCompleteRequest.java | 17 ++- .../protocol/util/PluginMessageUtil.java | 31 ++-- .../proxy/tablist/VelocityTabList.java | 17 ++- .../tablist/VelocityTabListEntryLegacy.java | 20 +++ .../proxy/tablist/VelocityTabListLegacy.java | 118 +++++++++++++++ 25 files changed, 485 insertions(+), 145 deletions(-) create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntryLegacy.java create mode 100644 proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index 7b096f194..941728e22 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -13,6 +13,8 @@ import java.util.Set; public enum ProtocolVersion { UNKNOWN(-1, "Unknown"), LEGACY(-2, "Legacy"), + MINECRAFT_1_7_2(4, "1.7.2"), + MINECRAFT_1_7_6(5, "1.7.6"), MINECRAFT_1_8(47, "1.8"), MINECRAFT_1_9(107, "1.9"), MINECRAFT_1_9_1(108, "1.9.1"), @@ -38,7 +40,7 @@ public enum ProtocolVersion { /** * Represents the lowest supported version. */ - public static final ProtocolVersion MINIMUM_VERSION = MINECRAFT_1_8; + public static final ProtocolVersion MINIMUM_VERSION = MINECRAFT_1_7_2; /** * Represents the highest supported version. */ diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/ConnectionTypes.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/ConnectionTypes.java index baf97c90f..150ab816e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/ConnectionTypes.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/ConnectionTypes.java @@ -3,6 +3,7 @@ package com.velocitypowered.proxy.connection; import com.velocitypowered.proxy.connection.backend.BackendConnectionPhases; import com.velocitypowered.proxy.connection.client.ClientConnectionPhases; import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConnectionType; +import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeHandshakeClientPhase; import com.velocitypowered.proxy.connection.util.ConnectionTypeImpl; /** @@ -24,6 +25,9 @@ public final class ConnectionTypes { public static final ConnectionType VANILLA = new ConnectionTypeImpl(ClientConnectionPhases.VANILLA, BackendConnectionPhases.VANILLA); + public static final ConnectionType UNDETERMINED_17 = new ConnectionTypeImpl( + LegacyForgeHandshakeClientPhase.NOT_STARTED, BackendConnectionPhases.UNKNOWN); + /** * Indicates that the connection is a 1.8-1.12 Forge * connection. diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index 5128efe9e..2f5d0f106 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -5,20 +5,17 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.tree.LiteralCommandNode; import com.velocitypowered.api.event.connection.PluginMessageEvent; -import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler; -import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants; import com.velocitypowered.proxy.connection.util.ConnectionMessages; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.packet.AvailableCommands; import com.velocitypowered.proxy.protocol.packet.AvailableCommands.ProtocolSuggestionProvider; import com.velocitypowered.proxy.protocol.packet.BossBar; import com.velocitypowered.proxy.protocol.packet.Disconnect; -import com.velocitypowered.proxy.protocol.packet.JoinGame; import com.velocitypowered.proxy.protocol.packet.KeepAlive; import com.velocitypowered.proxy.protocol.packet.PlayerListItem; import com.velocitypowered.proxy.protocol.packet.PluginMessage; @@ -103,8 +100,8 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { } if (PluginMessageUtil.isMcBrand(packet)) { - PluginMessage rewritten = PluginMessageUtil.rewriteMinecraftBrand(packet, - server.getVersion()); + PluginMessage rewritten = PluginMessageUtil.rewriteMinecraftBrand(packet, server.getVersion(), + playerConnection.getProtocolVersion()); playerConnection.write(rewritten); return true; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java index ba45251a7..06c69bfd4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java @@ -1,8 +1,11 @@ package com.velocitypowered.proxy.connection.client; +import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; +import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants; import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeHandshakeClientPhase; import com.velocitypowered.proxy.protocol.packet.PluginMessage; +import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; /** * Provides connection phase specific actions. 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 9593108a8..3d2e3a9f7 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 @@ -1,6 +1,7 @@ package com.velocitypowered.proxy.connection.client; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8; import static com.velocitypowered.proxy.protocol.util.PluginMessageUtil.constructChannelsPacket; import com.velocitypowered.api.event.connection.PluginMessageEvent; @@ -32,11 +33,9 @@ import io.netty.buffer.ByteBuf; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Queue; -import java.util.Set; import java.util.UUID; import net.kyori.text.TextComponent; import net.kyori.text.format.TextColor; @@ -218,7 +217,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { player.getKnownChannels().removeAll(PluginMessageUtil.getChannels(packet)); backendConn.write(packet); } else if (PluginMessageUtil.isMcBrand(packet)) { - backendConn.write(PluginMessageUtil.rewriteMinecraftBrand(packet, server.getVersion())); + backendConn.write(PluginMessageUtil + .rewriteMinecraftBrand(packet, server.getVersion(), player.getProtocolVersion())); } else { if (serverConn.getPhase() == BackendConnectionPhases.IN_TRANSITION) { // We must bypass the currently-connected server when forwarding Forge packets. @@ -378,8 +378,10 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { } // Clear any title from the previous server. - player.getMinecraftConnection() - .delayedWrite(TitlePacket.resetForProtocolVersion(player.getProtocolVersion())); + if (player.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) { + player.getMinecraftConnection() + .delayedWrite(TitlePacket.resetForProtocolVersion(player.getProtocolVersion())); + } // Flush everything player.getMinecraftConnection().flush(); 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 7589300fa..878e2fc40 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 @@ -46,6 +46,7 @@ import com.velocitypowered.proxy.protocol.packet.TitlePacket; import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import com.velocitypowered.proxy.tablist.VelocityTabList; +import com.velocitypowered.proxy.tablist.VelocityTabListLegacy; import com.velocitypowered.proxy.util.VelocityMessages; import com.velocitypowered.proxy.util.collect.CappedSet; import io.netty.buffer.ByteBufUtil; @@ -102,7 +103,11 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { ConnectedPlayer(VelocityServer server, GameProfile profile, MinecraftConnection minecraftConnection, @Nullable InetSocketAddress virtualHost) { this.server = server; - this.tabList = new VelocityTabList(minecraftConnection); + if (minecraftConnection.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + this.tabList = new VelocityTabList(minecraftConnection); + } else { + this.tabList = new VelocityTabListLegacy(minecraftConnection); + } this.profile = profile; this.minecraftConnection = minecraftConnection; this.virtualHost = virtualHost; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java index fdc16fb87..1eb25a2ba 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/HandshakeSessionHandler.java @@ -114,6 +114,10 @@ public class HandshakeSessionHandler implements MinecraftSessionHandler { if (handshake.getServerAddress().endsWith(LegacyForgeConstants.HANDSHAKE_HOSTNAME_TOKEN) && handshake.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_13) < 0) { return ConnectionTypes.LEGACY_FORGE; + } else if (handshake.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_7_6) <= 0) { + // 1.7 Forge will not notify us during handshake. UNDETERMINED will listen for incoming + // forge handshake attempts. Also sends a reset handshake packet on every transition. + return ConnectionTypes.UNDETERMINED_17; } else { // For later: See if we can determine Forge 1.13+ here, else this will need to be UNDETERMINED // until later in the cycle (most likely determinable during the LOGIN phase) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java index d0707588c..7f85107d7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java @@ -2,6 +2,7 @@ package com.velocitypowered.proxy.connection.client; import static com.google.common.net.UrlEscapers.urlFormParameterEscaper; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8; import static com.velocitypowered.proxy.VelocityServer.GSON; import static com.velocitypowered.proxy.connection.VelocityConstants.EMPTY_BYTE_ARRAY; import static com.velocitypowered.proxy.connection.VelocityConstants.VELOCITY_IP_FORWARDING_CHANNEL; @@ -249,7 +250,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler { } int threshold = server.getConfiguration().getCompressionThreshold(); - if (threshold >= 0) { + if (threshold >= 0 && mcConnection.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) { mcConnection.write(new SetCompression(threshold)); mcConnection.setCompressionThreshold(threshold); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeBackendPhase.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeBackendPhase.java index ad3610231..060525d5e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeBackendPhase.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeBackendPhase.java @@ -90,7 +90,7 @@ public enum LegacyForgeHandshakeBackendPhase implements BackendConnectionPhase { @Nullable private final Integer packetToAdvanceOn; /** - * Creates an instance of the {@link LegacyForgeHandshakeClientPhase}. + * Creates an instance of the {@link LegacyForgeHandshakeBackendPhase}. * * @param packetToAdvanceOn The ID of the packet discriminator that indicates * that the server has moved onto a new phase, and diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java index 907a8640f..ab6dbc75d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java @@ -3,11 +3,11 @@ package com.velocitypowered.proxy.protocol; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; +import com.google.common.base.Preconditions; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.util.GameProfile; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; - import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -19,6 +19,7 @@ public enum ProtocolUtils { /** * Reads a Minecraft-style VarInt from the specified {@code buf}. + * * @param buf the buffer to read from * @return the decoded VarInt */ @@ -40,6 +41,7 @@ public enum ProtocolUtils { /** * Writes a Minecraft-style VarInt to the specified {@code buf}. + * * @param buf the buffer to read from * @param value the integer to write */ @@ -60,8 +62,9 @@ public enum ProtocolUtils { } /** - * Reads a VarInt length-prefixed string from the {@code buf}, making sure to not go over - * {@code cap} size. + * Reads a VarInt length-prefixed string from the {@code buf}, making sure to not go over {@code + * cap} size. + * * @param buf the buffer to read from * @param cap the maximum size of the string, in UTF-8 character length * @return the decoded string @@ -85,6 +88,7 @@ public enum ProtocolUtils { /** * Writes the specified {@code str} to the {@code buf} with a VarInt prefix. + * * @param buf the buffer to write to * @param str the string to write */ @@ -101,6 +105,7 @@ public enum ProtocolUtils { /** * Reads a VarInt length-prefixed byte array from the {@code buf}, making sure to not go over * {@code cap} size. + * * @param buf the buffer to read from * @param cap the maximum size of the string, in UTF-8 character length * @return the byte array @@ -124,6 +129,7 @@ public enum ProtocolUtils { /** * Reads an VarInt-prefixed array of VarInt integers from the {@code buf}. + * * @param buf the buffer to read from * @return an array of integers */ @@ -139,6 +145,7 @@ public enum ProtocolUtils { /** * Reads an UUID from the {@code buf}. + * * @param buf the buffer to read from * @return the UUID from the buffer */ @@ -155,6 +162,7 @@ public enum ProtocolUtils { /** * Writes a list of {@link com.velocitypowered.api.util.GameProfile.Property} to the buffer. + * * @param buf the buffer to write to * @param properties the properties to serialize */ @@ -175,6 +183,7 @@ public enum ProtocolUtils { /** * Reads a list of {@link com.velocitypowered.api.util.GameProfile.Property} from the buffer. + * * @param buf the buffer to read from * @return the read properties */ @@ -194,12 +203,93 @@ public enum ProtocolUtils { return properties; } + private static final int FORGE_MAX_ARRAY_LENGTH = Integer.MAX_VALUE & 0x1FFF9A; + + /** + * Reads an byte array for legacy version 1.7 from the specified {@code buf} + * + * @param buf the buffer to read from + * @return the read byte array + */ + public static byte[] readByteArray17(ByteBuf buf) { + // Read in a 2 or 3 byte number that represents the length of the packet. (3 byte "shorts" for + // Forge only) + // No vanilla packet should give a 3 byte packet + int len = readExtendedForgeShort(buf); + + Preconditions.checkArgument(len <= (FORGE_MAX_ARRAY_LENGTH), + "Cannot receive array longer than %s (got %s bytes)", FORGE_MAX_ARRAY_LENGTH, len); + + byte[] ret = new byte[len]; + buf.readBytes(ret); + return ret; + } + + /** + * Writes an byte array for legacy version 1.7 to the specified {@code buf} + * + * @param b array + * @param buf buf + * @param allowExtended forge + */ + public static void writeByteArray17(byte[] b, ByteBuf buf, boolean allowExtended) { + if (allowExtended) { + Preconditions + .checkArgument(b.length <= (FORGE_MAX_ARRAY_LENGTH), + "Cannot send array longer than %s (got %s bytes)", FORGE_MAX_ARRAY_LENGTH, + b.length); + } else { + Preconditions.checkArgument(b.length <= Short.MAX_VALUE, + "Cannot send array longer than Short.MAX_VALUE (got %s bytes)", b.length); + } + // Write a 2 or 3 byte number that represents the length of the packet. (3 byte "shorts" for + // Forge only) + // No vanilla packet should give a 3 byte packet, this method will still retain vanilla + // behaviour. + writeExtendedForgeShort(buf, b.length); + buf.writeBytes(b); + } + + /** + * Reads a Minecraft-style extended short from the specified {@code buf}. + * + * @param buf buf to write + * @return read extended short + */ + public static int readExtendedForgeShort(ByteBuf buf) { + int low = buf.readUnsignedShort(); + int high = 0; + if ((low & 0x8000) != 0) { + low = low & 0x7FFF; + high = buf.readUnsignedByte(); + } + return ((high & 0xFF) << 15) | low; + } + + /** + * Writes a Minecraft-style extended short to the specified {@code buf}. + * + * @param buf buf to write + * @param toWrite the extended short to write + */ + public static void writeExtendedForgeShort(ByteBuf buf, int toWrite) { + int low = toWrite & 0x7FFF; + int high = (toWrite & 0x7F8000) >> 15; + if (high != 0) { + low = low | 0x8000; + } + buf.writeShort(low); + if (high != 0) { + buf.writeByte(high); + } + } + public enum Direction { SERVERBOUND, CLIENTBOUND; public StateRegistry.PacketRegistry.ProtocolRegistry getProtocolRegistry(StateRegistry state, - ProtocolVersion version) { + ProtocolVersion version) { return (this == SERVERBOUND ? state.serverbound : state.clientbound) .getProtocolRegistry(version); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index fd5c268b2..4444722cb 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -5,6 +5,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12_1; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_14; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_7_2; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9_4; @@ -44,14 +45,12 @@ import io.netty.util.collection.IntObjectHashMap; import io.netty.util.collection.IntObjectMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; - import java.util.Collections; import java.util.EnumMap; import java.util.EnumSet; import java.util.Map; import java.util.Objects; import java.util.function.Supplier; - import org.checkerframework.checker.nullness.qual.Nullable; public enum StateRegistry { @@ -59,20 +58,20 @@ public enum StateRegistry { HANDSHAKE { { serverbound.register(Handshake.class, Handshake::new, - map(0x00, MINECRAFT_1_8, false)); + map(0x00, MINECRAFT_1_7_2, false)); } }, STATUS { { serverbound.register(StatusRequest.class, () -> StatusRequest.INSTANCE, - map(0x00, MINECRAFT_1_8, false)); + map(0x00, MINECRAFT_1_7_2, false)); serverbound.register(StatusPing.class, StatusPing::new, - map(0x01, MINECRAFT_1_8, false)); + map(0x01, MINECRAFT_1_7_2, false)); clientbound.register(StatusResponse.class, StatusResponse::new, - map(0x00, MINECRAFT_1_8, false)); + map(0x00, MINECRAFT_1_7_2, false)); clientbound.register(StatusPing.class, StatusPing::new, - map(0x01, MINECRAFT_1_8, false)); + map(0x01, MINECRAFT_1_7_2, false)); } }, PLAY { @@ -81,33 +80,33 @@ public enum StateRegistry { clientbound.fallback = false; serverbound.register(TabCompleteRequest.class, TabCompleteRequest::new, - map(0x14, MINECRAFT_1_8, false), + map(0x14, MINECRAFT_1_7_2, false), map(0x01, MINECRAFT_1_9, false), map(0x02, MINECRAFT_1_12, false), map(0x01, MINECRAFT_1_12_1, false), map(0x05, MINECRAFT_1_13, false), map(0x06, MINECRAFT_1_14, false)); serverbound.register(Chat.class, Chat::new, - map(0x01, MINECRAFT_1_8, false), + map(0x01, MINECRAFT_1_7_2, false), map(0x02, MINECRAFT_1_9, false), map(0x03, MINECRAFT_1_12, false), map(0x02, MINECRAFT_1_12_1, false), map(0x03, MINECRAFT_1_14, false)); serverbound.register(ClientSettings.class, ClientSettings::new, - map(0x15, MINECRAFT_1_8, false), + map(0x15, MINECRAFT_1_7_2, false), map(0x04, MINECRAFT_1_9, false), map(0x05, MINECRAFT_1_12, false), map(0x04, MINECRAFT_1_12_1, false), map(0x05, MINECRAFT_1_14, false)); serverbound.register(PluginMessage.class, PluginMessage::new, - map(0x17, MINECRAFT_1_8, false), + map(0x17, MINECRAFT_1_7_2, false), map(0x09, MINECRAFT_1_9, false), map(0x0A, MINECRAFT_1_12, false), map(0x09, MINECRAFT_1_12_1, false), map(0x0A, MINECRAFT_1_13, false), map(0x0B, MINECRAFT_1_14, false)); serverbound.register(KeepAlive.class, KeepAlive::new, - map(0x00, MINECRAFT_1_8, false), + map(0x00, MINECRAFT_1_7_2, false), map(0x0B, MINECRAFT_1_9, false), map(0x0C, MINECRAFT_1_12, false), map(0x0B, MINECRAFT_1_12_1, false), @@ -123,37 +122,37 @@ public enum StateRegistry { clientbound.register(BossBar.class, BossBar::new, map(0x0C, MINECRAFT_1_9, false)); clientbound.register(Chat.class, Chat::new, - map(0x02, MINECRAFT_1_8, true), + map(0x02, MINECRAFT_1_7_2, true), map(0x0F, MINECRAFT_1_9, true), map(0x0E, MINECRAFT_1_13, true)); clientbound.register(TabCompleteResponse.class, TabCompleteResponse::new, - map(0x3A, MINECRAFT_1_8, false), + map(0x3A, MINECRAFT_1_7_2, false), map(0x0E, MINECRAFT_1_9, false), map(0x10, MINECRAFT_1_13, false)); clientbound.register(AvailableCommands.class, AvailableCommands::new, map(0x11, MINECRAFT_1_13, false)); clientbound.register(PluginMessage.class, PluginMessage::new, - map(0x3F, MINECRAFT_1_8, false), + map(0x3F, MINECRAFT_1_7_2, false), map(0x18, MINECRAFT_1_9, false), map(0x19, MINECRAFT_1_13, false), map(0x18, MINECRAFT_1_14, false)); clientbound.register(Disconnect.class, Disconnect::new, - map(0x40, MINECRAFT_1_8, false), + map(0x40, MINECRAFT_1_7_2, false), map(0x1A, MINECRAFT_1_9, false), map(0x1B, MINECRAFT_1_13, false), map(0x1A, MINECRAFT_1_14, false)); clientbound.register(KeepAlive.class, KeepAlive::new, - map(0x00, MINECRAFT_1_8, false), + map(0x00, MINECRAFT_1_7_2, false), map(0x1F, MINECRAFT_1_9, false), map(0x21, MINECRAFT_1_13, false), map(0x20, MINECRAFT_1_14, false)); clientbound.register(JoinGame.class, JoinGame::new, - map(0x01, MINECRAFT_1_8, false), + map(0x01, MINECRAFT_1_7_2, false), map(0x23, MINECRAFT_1_9, false), map(0x25, MINECRAFT_1_13, false), map(0x25, MINECRAFT_1_14, false)); clientbound.register(Respawn.class, Respawn::new, - map(0x07, MINECRAFT_1_8, true), + map(0x07, MINECRAFT_1_7_2, true), map(0x33, MINECRAFT_1_9, true), map(0x34, MINECRAFT_1_12, true), map(0x35, MINECRAFT_1_12_1, true), @@ -182,7 +181,7 @@ public enum StateRegistry { map(0x4B, MINECRAFT_1_13, true), map(0x4F, MINECRAFT_1_14, true)); clientbound.register(PlayerListItem.class, PlayerListItem::new, - map(0x38, MINECRAFT_1_8, false), + map(0x38, MINECRAFT_1_7_2, false), map(0x2D, MINECRAFT_1_9, false), map(0x2E, MINECRAFT_1_12_1, false), map(0x30, MINECRAFT_1_13, false), @@ -192,17 +191,17 @@ public enum StateRegistry { LOGIN { { serverbound.register(ServerLogin.class, ServerLogin::new, - map(0x00, MINECRAFT_1_8, false)); + map(0x00, MINECRAFT_1_7_2, false)); serverbound.register(EncryptionResponse.class, EncryptionResponse::new, - map(0x01, MINECRAFT_1_8, false)); + map(0x01, MINECRAFT_1_7_2, false)); serverbound.register(LoginPluginResponse.class, LoginPluginResponse::new, map(0x02, MINECRAFT_1_13, false)); clientbound.register(Disconnect.class, Disconnect::new, - map(0x00, MINECRAFT_1_8, false)); + map(0x00, MINECRAFT_1_7_2, false)); clientbound.register(EncryptionRequest.class, EncryptionRequest::new, - map(0x01, MINECRAFT_1_8, false)); + map(0x01, MINECRAFT_1_7_2, false)); clientbound.register(ServerLoginSuccess.class, ServerLoginSuccess::new, - map(0x02, MINECRAFT_1_8, false)); + map(0x02, MINECRAFT_1_7_2, false)); clientbound.register(SetCompression.class, SetCompression::new, map(0x03, MINECRAFT_1_8, false)); clientbound.register(LoginPluginMessage.class, LoginPluginMessage::new, @@ -246,7 +245,7 @@ public enum StateRegistry { }

void register(Class

clazz, Supplier

packetSupplier, - PacketMapping... mappings) { + PacketMapping... mappings) { if (mappings.length == 0) { throw new IllegalArgumentException("At least one mapping must be provided."); } @@ -382,8 +381,8 @@ public enum StateRegistry { /** * Creates a PacketMapping using the provided arguments. * - * @param id Packet Id - * @param version Protocol version + * @param id Packet Id + * @param version Protocol version * @param encodeOnly When true packet decoding will be disabled * @return PacketMapping with the provided arguments */ diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Chat.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Chat.java index c4761a667..2321b518f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Chat.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Chat.java @@ -56,7 +56,7 @@ public class Chat implements MinecraftPacket { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { message = ProtocolUtils.readString(buf); - if (direction == ProtocolUtils.Direction.CLIENTBOUND) { + if (direction == ProtocolUtils.Direction.CLIENTBOUND && version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { type = buf.readByte(); } } @@ -67,7 +67,7 @@ public class Chat implements MinecraftPacket { throw new IllegalStateException("Message is not specified"); } ProtocolUtils.writeString(buf, message); - if (direction == ProtocolUtils.Direction.CLIENTBOUND) { + if (direction == ProtocolUtils.Direction.CLIENTBOUND && version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { buf.writeByte(type); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettings.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettings.java index 80db8e997..361b1178e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettings.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ClientSettings.java @@ -13,6 +13,7 @@ public class ClientSettings implements MinecraftPacket { private byte viewDistance; private int chatVisibility; private boolean chatColors; + private byte difficulty; // 1.7 Protocol private short skinParts; private int mainHand; @@ -98,6 +99,11 @@ public class ClientSettings implements MinecraftPacket { this.viewDistance = buf.readByte(); this.chatVisibility = ProtocolUtils.readVarInt(buf); this.chatColors = buf.readBoolean(); + + if (version.compareTo(ProtocolVersion.MINECRAFT_1_7_6) <= 0) { + this.difficulty = buf.readByte(); + } + this.skinParts = buf.readUnsignedByte(); if (version.compareTo(ProtocolVersion.MINECRAFT_1_9) >= 0) { @@ -114,6 +120,11 @@ public class ClientSettings implements MinecraftPacket { buf.writeByte(viewDistance); ProtocolUtils.writeVarInt(buf, chatVisibility); buf.writeBoolean(chatColors); + + if (version.compareTo(ProtocolVersion.MINECRAFT_1_7_6) <= 0) { + buf.writeByte(difficulty); + } + buf.writeByte(skinParts); if (version.compareTo(ProtocolVersion.MINECRAFT_1_9) >= 0) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequest.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequest.java index a238226a2..a60165b6e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequest.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionRequest.java @@ -42,15 +42,27 @@ public class EncryptionRequest implements MinecraftPacket { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { this.serverId = ProtocolUtils.readString(buf, 20); - publicKey = ProtocolUtils.readByteArray(buf, 256); - verifyToken = ProtocolUtils.readByteArray(buf, 16); + + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + publicKey = ProtocolUtils.readByteArray(buf, 256); + verifyToken = ProtocolUtils.readByteArray(buf, 16); + } else { + publicKey = ProtocolUtils.readByteArray17(buf); + verifyToken = ProtocolUtils.readByteArray17(buf); + } } @Override public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { ProtocolUtils.writeString(buf, this.serverId); - ProtocolUtils.writeByteArray(buf, publicKey); - ProtocolUtils.writeByteArray(buf, verifyToken); + + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + ProtocolUtils.writeByteArray(buf, publicKey); + ProtocolUtils.writeByteArray(buf, verifyToken); + } else { + ProtocolUtils.writeByteArray17(publicKey, buf, false); + ProtocolUtils.writeByteArray17(verifyToken, buf, false); + } } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponse.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponse.java index 7d64ca4ca..04316a8f6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponse.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/EncryptionResponse.java @@ -40,14 +40,24 @@ public class EncryptionResponse implements MinecraftPacket { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - this.sharedSecret = ProtocolUtils.readByteArray(buf, 256); - this.verifyToken = ProtocolUtils.readByteArray(buf, 128); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + this.sharedSecret = ProtocolUtils.readByteArray(buf, 256); + this.verifyToken = ProtocolUtils.readByteArray(buf, 128); + } else { + this.sharedSecret = ProtocolUtils.readByteArray17(buf); + this.verifyToken = ProtocolUtils.readByteArray17(buf); + } } @Override public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - ProtocolUtils.writeByteArray(buf, sharedSecret); - ProtocolUtils.writeByteArray(buf, verifyToken); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + ProtocolUtils.writeByteArray(buf, sharedSecret); + ProtocolUtils.writeByteArray(buf, verifyToken); + } else { + ProtocolUtils.writeByteArray17(sharedSecret, buf, false); + ProtocolUtils.writeByteArray17(verifyToken, buf, false); + } } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java index af5eb6774..0b542803f 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java @@ -116,7 +116,9 @@ public class JoinGame implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_14) >= 0) { this.viewDistance = ProtocolUtils.readVarInt(buf); } - this.reducedDebugInfo = buf.readBoolean(); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + this.reducedDebugInfo = buf.readBoolean(); + } } @Override @@ -137,9 +139,11 @@ public class JoinGame implements MinecraftPacket { } ProtocolUtils.writeString(buf, levelType); if (version.compareTo(ProtocolVersion.MINECRAFT_1_14) >= 0) { - ProtocolUtils.writeVarInt(buf,viewDistance); + ProtocolUtils.writeVarInt(buf, viewDistance); + } + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + buf.writeBoolean(reducedDebugInfo); } - buf.writeBoolean(reducedDebugInfo); } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlive.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlive.java index ac6810a65..32febe2b6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlive.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/KeepAlive.java @@ -29,8 +29,10 @@ public class KeepAlive implements MinecraftPacket { public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { if (version.compareTo(ProtocolVersion.MINECRAFT_1_12_2) >= 0) { randomId = buf.readLong(); - } else { + } else if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { randomId = ProtocolUtils.readVarInt(buf); + } else { + randomId = buf.readInt(); } } @@ -38,8 +40,10 @@ public class KeepAlive implements MinecraftPacket { public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { if (version.compareTo(ProtocolVersion.MINECRAFT_1_12_2) >= 0) { buf.writeLong(randomId); - } else { + } else if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { ProtocolUtils.writeVarInt(buf, (int) randomId); + } else { + buf.writeInt((int) randomId); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PlayerListItem.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PlayerListItem.java index 4c31d92a4..1037ac765 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PlayerListItem.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PlayerListItem.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.UUID; import net.kyori.text.Component; import net.kyori.text.serializer.gson.GsonComponentSerializer; +import net.kyori.text.serializer.legacy.LegacyComponentSerializer; import org.checkerframework.checker.nullness.qual.Nullable; public class PlayerListItem implements MinecraftPacket { @@ -43,35 +44,43 @@ public class PlayerListItem implements MinecraftPacket { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - action = ProtocolUtils.readVarInt(buf); - int length = ProtocolUtils.readVarInt(buf); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + action = ProtocolUtils.readVarInt(buf); + int length = ProtocolUtils.readVarInt(buf); - for (int i = 0; i < length; i++) { - Item item = new Item(ProtocolUtils.readUuid(buf)); - items.add(item); - switch (action) { - case ADD_PLAYER: - item.setName(ProtocolUtils.readString(buf)); - item.setProperties(ProtocolUtils.readProperties(buf)); - item.setGameMode(ProtocolUtils.readVarInt(buf)); - item.setLatency(ProtocolUtils.readVarInt(buf)); - item.setDisplayName(readOptionalComponent(buf)); - break; - case UPDATE_GAMEMODE: - item.setGameMode(ProtocolUtils.readVarInt(buf)); - break; - case UPDATE_LATENCY: - item.setLatency(ProtocolUtils.readVarInt(buf)); - break; - case UPDATE_DISPLAY_NAME: - item.setDisplayName(readOptionalComponent(buf)); - break; - case REMOVE_PLAYER: - //Do nothing, all that is needed is the uuid - break; - default: - throw new UnsupportedOperationException("Unknown action " + action); + for (int i = 0; i < length; i++) { + Item item = new Item(ProtocolUtils.readUuid(buf)); + items.add(item); + switch (action) { + case ADD_PLAYER: + item.setName(ProtocolUtils.readString(buf)); + item.setProperties(ProtocolUtils.readProperties(buf)); + item.setGameMode(ProtocolUtils.readVarInt(buf)); + item.setLatency(ProtocolUtils.readVarInt(buf)); + item.setDisplayName(readOptionalComponent(buf)); + break; + case UPDATE_GAMEMODE: + item.setGameMode(ProtocolUtils.readVarInt(buf)); + break; + case UPDATE_LATENCY: + item.setLatency(ProtocolUtils.readVarInt(buf)); + break; + case UPDATE_DISPLAY_NAME: + item.setDisplayName(readOptionalComponent(buf)); + break; + case REMOVE_PLAYER: + //Do nothing, all that is needed is the uuid + break; + default: + throw new UnsupportedOperationException("Unknown action " + action); + } } + } else { + Item item = new Item(); + item.setName(ProtocolUtils.readString(buf)); + action = buf.readBoolean() ? ADD_PLAYER : REMOVE_PLAYER; + item.setLatency(buf.readShort()); + items.add(item); } } @@ -84,34 +93,47 @@ public class PlayerListItem implements MinecraftPacket { @Override public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - ProtocolUtils.writeVarInt(buf, action); - ProtocolUtils.writeVarInt(buf, items.size()); - for (Item item : items) { - ProtocolUtils.writeUuid(buf, item.getUuid()); - switch (action) { - case ADD_PLAYER: - ProtocolUtils.writeString(buf, item.getName()); - ProtocolUtils.writeProperties(buf, item.getProperties()); - ProtocolUtils.writeVarInt(buf, item.getGameMode()); - ProtocolUtils.writeVarInt(buf, item.getLatency()); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + ProtocolUtils.writeVarInt(buf, action); + ProtocolUtils.writeVarInt(buf, items.size()); + for (Item item : items) { + ProtocolUtils.writeUuid(buf, item.getUuid()); + switch (action) { + case ADD_PLAYER: + ProtocolUtils.writeString(buf, item.getName()); + ProtocolUtils.writeProperties(buf, item.getProperties()); + ProtocolUtils.writeVarInt(buf, item.getGameMode()); + ProtocolUtils.writeVarInt(buf, item.getLatency()); - writeDisplayName(buf, item.getDisplayName()); - break; - case UPDATE_GAMEMODE: - ProtocolUtils.writeVarInt(buf, item.getGameMode()); - break; - case UPDATE_LATENCY: - ProtocolUtils.writeVarInt(buf, item.getLatency()); - break; - case UPDATE_DISPLAY_NAME: - writeDisplayName(buf, item.getDisplayName()); - break; - case REMOVE_PLAYER: - //Do nothing, all that is needed is the uuid - break; - default: - throw new UnsupportedOperationException("Unknown action " + action); + writeDisplayName(buf, item.getDisplayName()); + break; + case UPDATE_GAMEMODE: + ProtocolUtils.writeVarInt(buf, item.getGameMode()); + break; + case UPDATE_LATENCY: + ProtocolUtils.writeVarInt(buf, item.getLatency()); + break; + case UPDATE_DISPLAY_NAME: + writeDisplayName(buf, item.getDisplayName()); + break; + case REMOVE_PLAYER: + //Do nothing, all that is needed is the uuid + break; + default: + throw new UnsupportedOperationException("Unknown action " + action); + } } + } else { + Item item = items.get(0); + if (item.getDisplayName() != null) { + String displayName = LegacyComponentSerializer.legacy().serialize(item.getDisplayName()); + ProtocolUtils.writeString(buf, + displayName.length() > 16 ? displayName.substring(0, 16) : displayName); + } else { + ProtocolUtils.writeString(buf, item.getName()); + } + buf.writeBoolean(action != REMOVE_PLAYER); + buf.writeShort(item.getLatency()); } } @@ -136,6 +158,10 @@ public class PlayerListItem implements MinecraftPacket { private int latency; private @Nullable Component displayName; + public Item() { + uuid = null; + } + public Item(UUID uuid) { this.uuid = uuid; } @@ -149,7 +175,7 @@ public class PlayerListItem implements MinecraftPacket { .setDisplayName(entry.getDisplayName().orElse(null)); } - public UUID getUuid() { + public @Nullable UUID getUuid() { return uuid; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessage.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessage.java index 7c5045568..487c1e2bc 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessage.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/PluginMessage.java @@ -7,9 +7,7 @@ import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; -import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; import org.checkerframework.checker.nullness.qual.Nullable; public class PluginMessage implements MinecraftPacket { @@ -50,8 +48,12 @@ public class PluginMessage implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_13) >= 0) { this.channel = transformLegacyToModernChannel(this.channel); } - this.data = new byte[buf.readableBytes()]; - buf.readBytes(data); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + this.data = new byte[buf.readableBytes()]; + buf.readBytes(data); + } else { + data = ProtocolUtils.readByteArray17(buf); + } } @Override @@ -64,7 +66,11 @@ public class PluginMessage implements MinecraftPacket { } else { ProtocolUtils.writeString(buf, this.channel); } - buf.writeBytes(data); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + buf.writeBytes(data); + } else { + ProtocolUtils.writeByteArray17(data, buf, true); // True for Forge support + } } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccess.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccess.java index 0d068bd7a..76b599466 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccess.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccess.java @@ -1,6 +1,7 @@ package com.velocitypowered.proxy.protocol.packet; import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.api.util.UuidUtils; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; @@ -45,7 +46,11 @@ public class ServerLoginSuccess implements MinecraftPacket { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - uuid = UUID.fromString(ProtocolUtils.readString(buf, 36)); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_7_6) >= 0) { + uuid = UUID.fromString(ProtocolUtils.readString(buf, 36)); + } else { + uuid = UuidUtils.fromUndashed(ProtocolUtils.readString(buf, 32)); + } username = ProtocolUtils.readString(buf, 16); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequest.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequest.java index 27afacaf9..e382861fe 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequest.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/TabCompleteRequest.java @@ -1,6 +1,7 @@ package com.velocitypowered.proxy.protocol.packet; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9; import com.google.common.base.MoreObjects; @@ -83,9 +84,11 @@ public class TabCompleteRequest implements MinecraftPacket { if (version.compareTo(MINECRAFT_1_9) >= 0) { this.assumeCommand = buf.readBoolean(); } - this.hasPosition = buf.readBoolean(); - if (hasPosition) { - this.position = buf.readLong(); + if (version.compareTo(MINECRAFT_1_8) >= 0) { + this.hasPosition = buf.readBoolean(); + if (hasPosition) { + this.position = buf.readLong(); + } } } } @@ -104,9 +107,11 @@ public class TabCompleteRequest implements MinecraftPacket { if (version.compareTo(MINECRAFT_1_9) >= 0) { buf.writeBoolean(assumeCommand); } - buf.writeBoolean(hasPosition); - if (hasPosition) { - buf.writeLong(position); + if (version.compareTo(MINECRAFT_1_8) >= 0) { + buf.writeBoolean(hasPosition); + if (hasPosition) { + buf.writeLong(position); + } } } } 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 9fef82a1f..d58ee95a7 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 @@ -126,27 +126,34 @@ public class PluginMessageUtil { * @param version the proxy version * @return the rewritten plugin message */ - public static PluginMessage rewriteMinecraftBrand(PluginMessage message, ProxyVersion version) { + public static PluginMessage rewriteMinecraftBrand(PluginMessage message, ProxyVersion version, + ProtocolVersion protocolVersion) { checkNotNull(message, "message"); checkNotNull(version, "version"); checkArgument(isMcBrand(message), "message is not a brand plugin message"); String toAppend = " (" + version.getName() + ")"; - byte[] rewrittenData; - ByteBuf rewrittenBuf = Unpooled.buffer(); - try { - String currentBrand = ProtocolUtils.readString(Unpooled.wrappedBuffer(message.getData())); - ProtocolUtils.writeString(rewrittenBuf, currentBrand + toAppend); - rewrittenData = new byte[rewrittenBuf.readableBytes()]; - rewrittenBuf.readBytes(rewrittenData); - } finally { - rewrittenBuf.release(); - } - PluginMessage newMsg = new PluginMessage(); newMsg.setChannel(message.getChannel()); + + byte[] rewrittenData; + if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + ByteBuf rewrittenBuf = Unpooled.buffer(); + try { + String currentBrand = ProtocolUtils.readString(Unpooled.wrappedBuffer(message.getData())); + ProtocolUtils.writeString(rewrittenBuf, currentBrand + toAppend); + rewrittenData = new byte[rewrittenBuf.readableBytes()]; + rewrittenBuf.readBytes(rewrittenData); + } finally { + rewrittenBuf.release(); + } + } else { + String currentBrand = new String(message.getData(), StandardCharsets.UTF_8); + rewrittenData = (currentBrand + toAppend).getBytes(); + } newMsg.setData(rewrittenData); + return newMsg; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java index aacf26012..09d8c01d5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabList.java @@ -7,6 +7,7 @@ import com.velocitypowered.api.util.GameProfile; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.protocol.packet.HeaderAndFooter; import com.velocitypowered.proxy.protocol.packet.PlayerListItem; +import com.velocitypowered.proxy.protocol.packet.PlayerListItem.Item; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -20,8 +21,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class VelocityTabList implements TabList { - private final MinecraftConnection connection; - private final Map entries = new ConcurrentHashMap<>(); + protected final MinecraftConnection connection; + protected final Map entries = new ConcurrentHashMap<>(); public VelocityTabList(MinecraftConnection connection) { this.connection = connection; @@ -76,9 +77,9 @@ public class VelocityTabList implements TabList { } /** - * Clears all entries from the tab list. Note that the entries are written with - * {@link MinecraftConnection#delayedWrite(Object)}, so make sure to do an explicit - * {@link MinecraftConnection#flush()}. + * Clears all entries from the tab list. Note that the entries are written with {@link + * MinecraftConnection#delayedWrite(Object)}, so make sure to do an explicit {@link + * MinecraftConnection#flush()}. */ public void clearAll() { List items = new ArrayList<>(); @@ -86,7 +87,9 @@ public class VelocityTabList implements TabList { items.add(PlayerListItem.Item.from(value)); } entries.clear(); - connection.delayedWrite(new PlayerListItem(PlayerListItem.REMOVE_PLAYER, items)); + if (!items.isEmpty()) { + connection.delayedWrite(new PlayerListItem(PlayerListItem.REMOVE_PLAYER, items)); + } } @Override @@ -102,12 +105,14 @@ public class VelocityTabList implements TabList { /** * Processes a tab list entry packet from the backend. + * * @param packet the packet to process */ public void processBackendPacket(PlayerListItem packet) { // Packets are already forwarded on, so no need to do that here for (PlayerListItem.Item item : packet.getItems()) { UUID uuid = item.getUuid(); + if (packet.getAction() != PlayerListItem.ADD_PLAYER && !entries.containsKey(uuid)) { // Sometimes UPDATE_GAMEMODE is sent before ADD_PLAYER so don't want to warn here continue; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntryLegacy.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntryLegacy.java new file mode 100644 index 000000000..7ef7b5dd7 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListEntryLegacy.java @@ -0,0 +1,20 @@ +package com.velocitypowered.proxy.tablist; + +import com.velocitypowered.api.proxy.player.TabListEntry; +import com.velocitypowered.api.util.GameProfile; +import net.kyori.text.Component; +import org.checkerframework.checker.nullness.qual.Nullable; + +public class VelocityTabListEntryLegacy extends VelocityTabListEntry { + + VelocityTabListEntryLegacy(VelocityTabListLegacy tabList, GameProfile profile, + @Nullable Component displayName, int latency, int gameMode) { + super(tabList, profile, displayName, latency, gameMode); + } + + @Override + public TabListEntry setDisplayName(@Nullable Component displayName) { + getTabList().removeEntry(getProfile().getId()); // We have to remove first if updating + return super.setDisplayName(displayName); + } +} diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java new file mode 100644 index 000000000..31b494545 --- /dev/null +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java @@ -0,0 +1,118 @@ +package com.velocitypowered.proxy.tablist; + +import com.google.common.collect.ImmutableList; +import com.velocitypowered.api.proxy.player.TabListEntry; +import com.velocitypowered.api.util.GameProfile; +import com.velocitypowered.proxy.connection.MinecraftConnection; +import com.velocitypowered.proxy.protocol.packet.PlayerListItem; +import com.velocitypowered.proxy.protocol.packet.PlayerListItem.Item; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import net.kyori.text.Component; +import net.kyori.text.serializer.legacy.LegacyComponentSerializer; +import net.kyori.text.serializer.plain.PlainComponentSerializer; +import org.checkerframework.checker.nullness.qual.Nullable; + +public class VelocityTabListLegacy extends VelocityTabList { + + private final Map nameMapping = new ConcurrentHashMap<>(); + + public VelocityTabListLegacy(MinecraftConnection connection) { + super(connection); + } + + @Override + public void setHeaderAndFooter(Component header, Component footer) { + } + + @Override + public void clearHeaderAndFooter() { + } + + @Override + public void addEntry(TabListEntry entry) { + super.addEntry(entry); + nameMapping.put(entry.getProfile().getName(), entry.getProfile().getId()); + } + + @Override + public Optional removeEntry(UUID uuid) { + Optional entry = super.removeEntry(uuid); + entry.map(TabListEntry::getProfile).map(GameProfile::getName).ifPresent(nameMapping::remove); + return entry; + } + + @Override + public void clearAll() { + for (TabListEntry value : entries.values()) { + connection.delayedWrite(new PlayerListItem(PlayerListItem.REMOVE_PLAYER, + Collections.singletonList(PlayerListItem.Item.from(value)))); + } + entries.clear(); + } + + @Override + public void processBackendPacket(PlayerListItem packet) { + + Item item = packet.getItems().get(0); // Only one item per packet in 1.7 + + Component displayName = LegacyComponentSerializer.legacy().deserialize(item.getName()); + String strippedName = PlainComponentSerializer.INSTANCE.serialize(displayName); + + switch (packet.getAction()) { + case PlayerListItem.ADD_PLAYER: + if (nameMapping.containsKey(strippedName)) { // ADD_PLAYER also used for updating ping + VelocityTabListEntry entry = entries.get(nameMapping.get(strippedName)); + if (entry != null) { + entry.setLatency(item.getLatency()); + } + } else { + UUID uuid = UUID.randomUUID(); // Use a fake uuid to preserve function of custom entries + nameMapping.put(strippedName, uuid); + entries.put(uuid, (VelocityTabListEntry) TabListEntry.builder() + .tabList(this) + .profile(new GameProfile(uuid, strippedName, ImmutableList.of())) + .displayName(displayName) + .latency(item.getLatency()) + .build()); + } + break; + case PlayerListItem.REMOVE_PLAYER: + UUID removedUuid = nameMapping.remove(strippedName); + if (removedUuid != null) { + entries.remove(removedUuid); + } + break; + default: + // For 1.7 there is only add and remove + break; + } + + } + + @Override + void updateEntry(int action, TabListEntry entry) { + if (entries.containsKey(entry.getProfile().getId())) { + switch (action) { + case PlayerListItem.UPDATE_LATENCY: + case PlayerListItem.UPDATE_DISPLAY_NAME: // Add here because we removed beforehand + connection + .write(new PlayerListItem(PlayerListItem.ADD_PLAYER, // ADD_PLAYER also updates ping + Collections.singletonList(PlayerListItem.Item.from(entry)))); + break; + default: + // Can't do anything else + break; + } + } + } + + @Override + public TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency, + int gameMode) { + return new VelocityTabListEntryLegacy(this, profile, displayName, latency, gameMode); + } +} From 661ec3103ac8fd5d51a9dae3e08994fede649024 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 9 Aug 2019 15:38:36 -0400 Subject: [PATCH 05/14] Bump to Guice 4.2.2 for Java 11 plugin support --- api/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/build.gradle b/api/build.gradle index 2a43ac049..a9e466865 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -24,7 +24,7 @@ dependencies { compile "net.kyori:text-serializer-plain:${textVersion}" compile 'com.moandjiezana.toml:toml4j:0.7.2' compile "org.slf4j:slf4j-api:${slf4jVersion}" - compile 'com.google.inject:guice:4.2.0' + compile 'com.google.inject:guice:4.2.2' compile "org.checkerframework:checker-qual:${checkerFrameworkVersion}" compile "org.spongepowered:configurate-hocon:${configurateVersion}" From b3ca066a177d188d803fcb8664692d01c8f4ea7f Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 10 Aug 2019 14:08:45 -0400 Subject: [PATCH 06/14] Lower write water mark to 1MB --- .../com/velocitypowered/proxy/network/ConnectionManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java index 0323d24a3..765af2261 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/network/ConnectionManager.java @@ -34,7 +34,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; public final class ConnectionManager { - private static final WriteBufferWaterMark SERVER_WRITE_MARK = new WriteBufferWaterMark(1 << 21, + private static final WriteBufferWaterMark SERVER_WRITE_MARK = new WriteBufferWaterMark(1 << 20, 1 << 21); private static final Logger LOGGER = LogManager.getLogger(ConnectionManager.class); private final Map endpoints = new HashMap<>(); From 7f3e7a82c4559fb494a86cd2509c385a76786660 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sun, 11 Aug 2019 20:36:00 -0400 Subject: [PATCH 07/14] Update text 3.0.2 cc @lucko --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5add3e122..8d9b45507 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ allprojects { ext { // dependency versions - textVersion = '3.0.1' + textVersion = '3.0.2' junitVersion = '5.3.0-M1' slf4jVersion = '1.7.25' log4jVersion = '2.11.2' From ca81b055510163b5616ff0718e45e7c71c9b0eb1 Mon Sep 17 00:00:00 2001 From: Gabik21 Date: Fri, 16 Aug 2019 11:50:49 +0200 Subject: [PATCH 08/14] Remove no longer used imports --- .../connection/client/ClientConnectionPhase.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java index 06c69bfd4..c8727e82b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java @@ -1,11 +1,8 @@ package com.velocitypowered.proxy.connection.client; -import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.connection.backend.VelocityServerConnection; -import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants; import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeHandshakeClientPhase; import com.velocitypowered.proxy.protocol.packet.PluginMessage; -import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; /** * Provides connection phase specific actions. @@ -16,8 +13,7 @@ import com.velocitypowered.proxy.protocol.util.PluginMessageUtil; public interface ClientConnectionPhase { /** - * Handle a plugin message in the context of - * this phase. + * Handle a plugin message in the context of this phase. * * @param player The player * @param message The message to handle @@ -31,8 +27,7 @@ public interface ClientConnectionPhase { } /** - * Instruct Velocity to reset the connection phase - * back to its default for the connection type. + * Instruct Velocity to reset the connection phase back to its default for the connection type. * * @param player The player */ @@ -40,8 +35,7 @@ public interface ClientConnectionPhase { } /** - * Perform actions just as the player joins the - * server. + * Perform actions just as the player joins the server. * * @param player The player */ @@ -50,6 +44,7 @@ public interface ClientConnectionPhase { /** * Indicates whether the connection is considered complete. + * * @return true if so */ default boolean consideredComplete() { From d68cbbd9060a43a6d602094d5a857140cf8bf219 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 17 Aug 2019 20:12:09 -0400 Subject: [PATCH 09/14] Remove inaccurate "Status" section I'm just one person, I can't keep this stuff updated everywhere. --- README.md | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/README.md b/README.md index c83e79669..4b35a9a02 100644 --- a/README.md +++ b/README.md @@ -34,15 +34,4 @@ Once you've built Velocity, you can copy and run the `-all` JAR from and you can configure it from there. Alternatively, you can get the proxy JAR from the [downloads](https://www.velocitypowered.com/downloads) -page. - -## Status - -Velocity is currently in beta. Production networks are successfully running -Velocity with many hundreds of concurrent players online, but your mileage -may vary. - -Velocity supports Minecraft 1.8-1.14.4. Velocity is best supported with Paper -and SpongeVanilla. Minecraft Forge is fully supported but mod compatibility -may vary. Generally, Velocity will support many mods better than BungeeCord -or Waterfall do but compatibility can not always be ensured. +page. \ No newline at end of file From dbfbd1e2a982343026ff1b25855ff562ee7bfa99 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 17 Aug 2019 20:17:12 -0400 Subject: [PATCH 10/14] Rename ConnectedPlayer#minecraftConnection -> ConnectedPlayer#connection This is consistent with VelocityServerConnection --- .../velocitypowered/proxy/VelocityServer.java | 2 +- .../backend/BackendPlaySessionHandler.java | 5 +- .../backend/TransitionSessionHandler.java | 8 +-- .../backend/VelocityServerConnection.java | 6 +- .../client/ClientPlaySessionHandler.java | 27 ++++---- .../connection/client/ConnectedPlayer.java | 61 +++++++++---------- .../LegacyForgeHandshakeBackendPhase.java | 2 +- .../LegacyForgeHandshakeClientPhase.java | 2 +- .../proxy/util/bossbar/VelocityBossBar.java | 2 +- 9 files changed, 55 insertions(+), 60 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java index 5b032e180..2f260cce6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java @@ -505,7 +505,7 @@ public class VelocityServer implements ProxyServer { Preconditions.checkNotNull(component, "component"); Chat chat = Chat.createClientbound(component); for (ConnectedPlayer player : connectionsByUuid.values()) { - player.getMinecraftConnection().write(chat); + player.getConnection().write(chat); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java index 571a7323c..b43fc0a2a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/BackendPlaySessionHandler.java @@ -5,20 +5,17 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.tree.LiteralCommandNode; import com.velocitypowered.api.event.connection.PluginMessageEvent; -import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.client.ClientPlaySessionHandler; -import com.velocitypowered.proxy.connection.forge.legacy.LegacyForgeConstants; import com.velocitypowered.proxy.connection.util.ConnectionMessages; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.packet.AvailableCommands; import com.velocitypowered.proxy.protocol.packet.AvailableCommands.ProtocolSuggestionProvider; import com.velocitypowered.proxy.protocol.packet.BossBar; import com.velocitypowered.proxy.protocol.packet.Disconnect; -import com.velocitypowered.proxy.protocol.packet.JoinGame; import com.velocitypowered.proxy.protocol.packet.KeepAlive; import com.velocitypowered.proxy.protocol.packet.PlayerListItem; import com.velocitypowered.proxy.protocol.packet.PluginMessage; @@ -39,7 +36,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler { BackendPlaySessionHandler(VelocityServer server, VelocityServerConnection serverConn) { this.server = server; this.serverConn = serverConn; - this.playerConnection = serverConn.getPlayer().getMinecraftConnection(); + this.playerConnection = serverConn.getPlayer().getConnection(); MinecraftSessionHandler psh = playerConnection.getSessionHandler(); if (!(psh instanceof ClientPlaySessionHandler)) { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java index b8d7ed75f..1c6a0b05b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/TransitionSessionHandler.java @@ -84,13 +84,13 @@ public class TransitionSessionHandler implements MinecraftSessionHandler { .whenCompleteAsync((x, error) -> { // Strap on the ClientPlaySessionHandler if required. ClientPlaySessionHandler playHandler; - if (serverConn.getPlayer().getMinecraftConnection().getSessionHandler() + if (serverConn.getPlayer().getConnection().getSessionHandler() instanceof ClientPlaySessionHandler) { - playHandler = (ClientPlaySessionHandler) serverConn.getPlayer().getMinecraftConnection() + playHandler = (ClientPlaySessionHandler) serverConn.getPlayer().getConnection() .getSessionHandler(); } else { playHandler = new ClientPlaySessionHandler(server, serverConn.getPlayer()); - serverConn.getPlayer().getMinecraftConnection().setSessionHandler(playHandler); + serverConn.getPlayer().getConnection().setSessionHandler(playHandler); } playHandler.handleBackendJoinGame(packet, serverConn); @@ -167,7 +167,7 @@ public class TransitionSessionHandler implements MinecraftSessionHandler { return true; } - serverConn.getPlayer().getMinecraftConnection().write(packet.retain()); + serverConn.getPlayer().getConnection().write(packet.retain()); return true; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java index 5922238a1..42d06fd89 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/backend/VelocityServerConnection.java @@ -76,7 +76,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation, CompletableFuture result = new CompletableFuture<>(); // Note: we use the event loop for the connection the player is on. This reduces context // switches. - server.createBootstrap(proxyPlayer.getMinecraftConnection().eventLoop()) + server.createBootstrap(proxyPlayer.getConnection().eventLoop()) .handler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { @@ -138,13 +138,13 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation, PlayerInfoForwarding forwardingMode = server.getConfiguration().getPlayerInfoForwardingMode(); // Initiate the handshake. - ProtocolVersion protocolVersion = proxyPlayer.getMinecraftConnection().getNextProtocolVersion(); + ProtocolVersion protocolVersion = proxyPlayer.getConnection().getNextProtocolVersion(); Handshake handshake = new Handshake(); handshake.setNextStatus(StateRegistry.LOGIN_ID); handshake.setProtocolVersion(protocolVersion); if (forwardingMode == PlayerInfoForwarding.LEGACY) { handshake.setServerAddress(createLegacyForwardingAddress()); - } else if (proxyPlayer.getMinecraftConnection().getType() == ConnectionTypes.LEGACY_FORGE) { + } else if (proxyPlayer.getConnection().getType() == ConnectionTypes.LEGACY_FORGE) { handshake.setServerAddress(handshake.getServerAddress() + HANDSHAKE_HOSTNAME_TOKEN); } else { handshake.setServerAddress(registeredServer.getServerInfo().getAddress().getHostString()); 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 32a67b755..2ae0d08a1 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 @@ -40,7 +40,6 @@ import java.util.List; import java.util.Optional; import java.util.Queue; import java.util.UUID; -import net.kyori.text.Component; import net.kyori.text.TextComponent; import net.kyori.text.format.TextColor; import org.apache.logging.log4j.LogManager; @@ -78,7 +77,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { .getProtocolVersion()); if (!channels.isEmpty()) { PluginMessage register = constructChannelsPacket(player.getProtocolVersion(), channels); - player.getMinecraftConnection().write(register); + player.getConnection().write(register); player.getKnownChannels().addAll(channels); } } @@ -275,7 +274,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { public void writabilityChanged() { VelocityServerConnection serverConn = player.getConnectedServer(); if (serverConn != null) { - boolean writable = player.getMinecraftConnection().getChannel().isWritable(); + boolean writable = player.getConnection().getChannel().isWritable(); MinecraftConnection smc = serverConn.getConnection(); if (smc != null) { smc.setAutoReading(writable); @@ -295,7 +294,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { if (!spawned) { // Nothing special to do with regards to spawning the player spawned = true; - player.getMinecraftConnection().delayedWrite(joinGame); + player.getConnection().delayedWrite(joinGame); // Required for Legacy Forge player.getPhase().onFirstJoin(player); @@ -315,12 +314,12 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { // Most notably, by having the client accept the join game packet, we can work around the need // to perform entity ID rewrites, eliminating potential issues from rewriting packets and // improving compatibility with mods. - player.getMinecraftConnection().delayedWrite(joinGame); + player.getConnection().delayedWrite(joinGame); int tempDim = joinGame.getDimension() == 0 ? -1 : 0; - player.getMinecraftConnection().delayedWrite( + player.getConnection().delayedWrite( new Respawn(tempDim, joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType())); - player.getMinecraftConnection().delayedWrite( + player.getConnection().delayedWrite( new Respawn(joinGame.getDimension(), joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType())); } @@ -331,7 +330,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { BossBar deletePacket = new BossBar(); deletePacket.setUuid(serverBossBar); deletePacket.setAction(BossBar.REMOVE); - player.getMinecraftConnection().delayedWrite(deletePacket); + player.getConnection().delayedWrite(deletePacket); } serverBossBars.clear(); @@ -348,11 +347,11 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { } // Clear any title from the previous server. - player.getMinecraftConnection() + player.getConnection() .delayedWrite(TitlePacket.resetForProtocolVersion(player.getProtocolVersion())); // Flush everything - player.getMinecraftConnection().flush(); + player.getConnection().flush(); serverMc.flush(); destination.completeJoin(); } @@ -410,7 +409,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { resp.setLength(length); resp.getOffers().addAll(offers); - player.getMinecraftConnection().write(resp); + player.getConnection().write(resp); return true; } @@ -450,7 +449,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { response.getOffers().add(new Offer(offer, null)); } response.getOffers().sort(null); - player.getMinecraftConnection().write(response); + player.getConnection().write(response); } catch (Exception e) { logger.error("Unable to provide tab list completions for {} for command '{}'", player.getUsername(), @@ -469,8 +468,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { for (String s : e.getSuggestions()) { response.getOffers().add(new Offer(s)); } - player.getMinecraftConnection().write(response); - }, player.getMinecraftConnection().eventLoop()); + player.getConnection().write(response); + }, player.getConnection().eventLoop()); } /** 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 19d19d9c7..83c6c86a6 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 @@ -58,7 +58,6 @@ import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; -import java.util.concurrent.ExecutionException; import java.util.concurrent.ThreadLocalRandom; import net.kyori.text.Component; import net.kyori.text.TextComponent; @@ -84,7 +83,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { /** * The actual Minecraft connection. This is actually a wrapper object around the Netty channel. */ - private final MinecraftConnection minecraftConnection; + private final MinecraftConnection connection; private final @Nullable InetSocketAddress virtualHost; private GameProfile profile; private PermissionFunction permissionFunction; @@ -103,14 +102,14 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { private @MonotonicNonNull List serversToTry = null; ConnectedPlayer(VelocityServer server, GameProfile profile, - MinecraftConnection minecraftConnection, @Nullable InetSocketAddress virtualHost) { + MinecraftConnection connection, @Nullable InetSocketAddress virtualHost) { this.server = server; - this.tabList = new VelocityTabList(minecraftConnection); + this.tabList = new VelocityTabList(connection); this.profile = profile; - this.minecraftConnection = minecraftConnection; + this.connection = connection; this.virtualHost = virtualHost; this.permissionFunction = PermissionFunction.ALWAYS_UNDEFINED; - this.connectionPhase = minecraftConnection.getType().getInitialClientPhase(); + this.connectionPhase = connection.getType().getInitialClientPhase(); this.knownChannels = CappedSet.create(MAX_PLUGIN_CHANNELS); } @@ -134,8 +133,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { return profile; } - public MinecraftConnection getMinecraftConnection() { - return minecraftConnection; + public MinecraftConnection getConnection() { + return connection; } @Override @@ -170,7 +169,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { @Override public InetSocketAddress getRemoteAddress() { - return (InetSocketAddress) minecraftConnection.getRemoteAddress(); + return (InetSocketAddress) connection.getRemoteAddress(); } @Override @@ -184,12 +183,12 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { @Override public boolean isActive() { - return minecraftConnection.getChannel().isActive(); + return connection.getChannel().isActive(); } @Override public ProtocolVersion getProtocolVersion() { - return minecraftConnection.getProtocolVersion(); + return connection.getProtocolVersion(); } @Override @@ -205,7 +204,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { TitlePacket pkt = new TitlePacket(); pkt.setAction(TitlePacket.SET_ACTION_BAR); pkt.setComponent(GsonComponentSerializer.INSTANCE.serialize(component)); - minecraftConnection.write(pkt); + connection.write(pkt); return; } else { // Due to issues with action bar packets, we'll need to convert the text message into a @@ -221,7 +220,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { Chat chat = new Chat(); chat.setType(pos); chat.setMessage(json); - minecraftConnection.write(chat); + connection.write(chat); } @Override @@ -258,23 +257,23 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { public void disconnect(Component reason) { logger.info("{} has disconnected: {}", this, LegacyComponentSerializer.legacy().serialize(reason)); - minecraftConnection.closeWith(Disconnect.create(reason)); + connection.closeWith(Disconnect.create(reason)); } @Override public void sendTitle(Title title) { Preconditions.checkNotNull(title, "title"); - ProtocolVersion protocolVersion = minecraftConnection.getProtocolVersion(); + ProtocolVersion protocolVersion = connection.getProtocolVersion(); if (title.equals(Titles.reset())) { - minecraftConnection.write(TitlePacket.resetForProtocolVersion(protocolVersion)); + connection.write(TitlePacket.resetForProtocolVersion(protocolVersion)); } else if (title.equals(Titles.hide())) { - minecraftConnection.write(TitlePacket.hideForProtocolVersion(protocolVersion)); + connection.write(TitlePacket.hideForProtocolVersion(protocolVersion)); } else if (title instanceof TextTitle) { TextTitle tt = (TextTitle) title; if (tt.isResetBeforeSend()) { - minecraftConnection.delayedWrite(TitlePacket.resetForProtocolVersion(protocolVersion)); + connection.delayedWrite(TitlePacket.resetForProtocolVersion(protocolVersion)); } Optional titleText = tt.getTitle(); @@ -282,7 +281,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { TitlePacket titlePkt = new TitlePacket(); titlePkt.setAction(TitlePacket.SET_TITLE); titlePkt.setComponent(GsonComponentSerializer.INSTANCE.serialize(titleText.get())); - minecraftConnection.delayedWrite(titlePkt); + connection.delayedWrite(titlePkt); } Optional subtitleText = tt.getSubtitle(); @@ -290,7 +289,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { TitlePacket titlePkt = new TitlePacket(); titlePkt.setAction(TitlePacket.SET_SUBTITLE); titlePkt.setComponent(GsonComponentSerializer.INSTANCE.serialize(subtitleText.get())); - minecraftConnection.delayedWrite(titlePkt); + connection.delayedWrite(titlePkt); } if (tt.areTimesSet()) { @@ -298,9 +297,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { timesPkt.setFadeIn(tt.getFadeIn()); timesPkt.setStay(tt.getStay()); timesPkt.setFadeOut(tt.getFadeOut()); - minecraftConnection.delayedWrite(timesPkt); + connection.delayedWrite(timesPkt); } - minecraftConnection.flush(); + connection.flush(); } else { throw new IllegalArgumentException("Unknown title class " + title.getClass().getName()); } @@ -454,7 +453,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { } else { sendMessage(VelocityMessages.MOVED_TO_NEW_SERVER.append(friendlyReason)); } - }, minecraftConnection.eventLoop()); + }, connection.eventLoop()); } else if (event.getResult() instanceof Notify) { Notify res = (Notify) event.getResult(); if (event.kickedDuringServerConnect()) { @@ -466,7 +465,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { // In case someone gets creative, assume we want to disconnect the player. disconnect(friendlyReason); } - }, minecraftConnection.eventLoop()); + }, connection.eventLoop()); } /** @@ -579,7 +578,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { Preconditions.checkNotNull(identifier, "identifier"); Preconditions.checkNotNull(data, "data"); PluginMessage message = new PluginMessage(identifier.getId(), Unpooled.wrappedBuffer(data)); - minecraftConnection.write(message); + connection.write(message); return true; } @@ -598,7 +597,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { ResourcePackRequest request = new ResourcePackRequest(); request.setUrl(url); request.setHash(""); - minecraftConnection.write(request); + connection.write(request); } @Override @@ -610,7 +609,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { ResourcePackRequest request = new ResourcePackRequest(); request.setUrl(url); request.setHash(ByteBufUtil.hexDump(hash)); - minecraftConnection.write(request); + connection.write(request); } /** @@ -619,10 +618,10 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { * ID last sent by the server. */ public void sendKeepAlive() { - if (minecraftConnection.getState() == StateRegistry.PLAY) { + if (connection.getState() == StateRegistry.PLAY) { KeepAlive keepAlive = new KeepAlive(); keepAlive.setRandomId(ThreadLocalRandom.current().nextLong()); - minecraftConnection.write(keepAlive); + connection.write(keepAlive); } } @@ -749,7 +748,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { } else if ((status != null && !status.isSuccessful())) { resetInFlightConnection(); } - }, minecraftConnection.eventLoop()) + }, connection.eventLoop()) .thenApply(x -> x); } @@ -782,7 +781,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { // The only remaining value is successful (no need to do anything!) break; } - }, minecraftConnection.eventLoop()) + }, connection.eventLoop()) .thenApply(Result::isSuccessful); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeBackendPhase.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeBackendPhase.java index 1c8594a22..bf44814aa 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeBackendPhase.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeBackendPhase.java @@ -114,7 +114,7 @@ public enum LegacyForgeHandshakeBackendPhase implements BackendConnectionPhase { serverConnection.setConnectionPhase(newPhase); // Write the packet to the player, we don't need it now. - player.getMinecraftConnection().write(message.retain()); + player.getConnection().write(message.retain()); return true; } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeClientPhase.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeClientPhase.java index f75dc04b7..b394cb137 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeClientPhase.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/forge/legacy/LegacyForgeHandshakeClientPhase.java @@ -135,7 +135,7 @@ public enum LegacyForgeHandshakeClientPhase implements ClientConnectionPhase { COMPLETE(null) { @Override public void resetConnectionPhase(ConnectedPlayer player) { - player.getMinecraftConnection().write(LegacyForgeUtil.resetPacket()); + player.getConnection().write(LegacyForgeUtil.resetPacket()); player.setPhase(LegacyForgeHandshakeClientPhase.NOT_STARTED); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/bossbar/VelocityBossBar.java b/proxy/src/main/java/com/velocitypowered/proxy/util/bossbar/VelocityBossBar.java index 98dc81d50..6b4d9b01a 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/bossbar/VelocityBossBar.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/bossbar/VelocityBossBar.java @@ -271,6 +271,6 @@ public class VelocityBossBar implements com.velocitypowered.api.util.bossbar.Bos private void sendPacket(Player player, MinecraftPacket packet) { ConnectedPlayer connected = (ConnectedPlayer) player; - connected.getMinecraftConnection().write(packet); + connected.getConnection().write(packet); } } From 592517b9f3b0a042eaa431b77c377096c214f2b0 Mon Sep 17 00:00:00 2001 From: Gabik21 Date: Thu, 29 Aug 2019 19:58:00 +0200 Subject: [PATCH 11/14] Remove unnessecary diff --- .../connection/client/ClientConnectionPhase.java | 10 ++++++---- .../proxy/protocol/ProtocolUtils.java | 13 ++----------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java index c8727e82b..ba45251a7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientConnectionPhase.java @@ -13,7 +13,8 @@ import com.velocitypowered.proxy.protocol.packet.PluginMessage; public interface ClientConnectionPhase { /** - * Handle a plugin message in the context of this phase. + * Handle a plugin message in the context of + * this phase. * * @param player The player * @param message The message to handle @@ -27,7 +28,8 @@ public interface ClientConnectionPhase { } /** - * Instruct Velocity to reset the connection phase back to its default for the connection type. + * Instruct Velocity to reset the connection phase + * back to its default for the connection type. * * @param player The player */ @@ -35,7 +37,8 @@ public interface ClientConnectionPhase { } /** - * Perform actions just as the player joins the server. + * Perform actions just as the player joins the + * server. * * @param player The player */ @@ -44,7 +47,6 @@ public interface ClientConnectionPhase { /** * Indicates whether the connection is considered complete. - * * @return true if so */ default boolean consideredComplete() { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java index 77b628e4f..555885575 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java @@ -19,7 +19,6 @@ public enum ProtocolUtils { /** * Reads a Minecraft-style VarInt from the specified {@code buf}. - * * @param buf the buffer to read from * @return the decoded VarInt */ @@ -41,7 +40,6 @@ public enum ProtocolUtils { /** * Writes a Minecraft-style VarInt to the specified {@code buf}. - * * @param buf the buffer to read from * @param value the integer to write */ @@ -62,9 +60,8 @@ public enum ProtocolUtils { } /** - * Reads a VarInt length-prefixed string from the {@code buf}, making sure to not go over {@code - * cap} size. - * + * Reads a VarInt length-prefixed string from the {@code buf}, making sure to not go over + * {@code cap} size. * @param buf the buffer to read from * @param cap the maximum size of the string, in UTF-8 character length * @return the decoded string @@ -88,7 +85,6 @@ public enum ProtocolUtils { /** * Writes the specified {@code str} to the {@code buf} with a VarInt prefix. - * * @param buf the buffer to write to * @param str the string to write */ @@ -105,7 +101,6 @@ public enum ProtocolUtils { /** * Reads a VarInt length-prefixed byte array from the {@code buf}, making sure to not go over * {@code cap} size. - * * @param buf the buffer to read from * @param cap the maximum size of the string, in UTF-8 character length * @return the byte array @@ -129,7 +124,6 @@ public enum ProtocolUtils { /** * Reads an VarInt-prefixed array of VarInt integers from the {@code buf}. - * * @param buf the buffer to read from * @return an array of integers */ @@ -145,7 +139,6 @@ public enum ProtocolUtils { /** * Reads an UUID from the {@code buf}. - * * @param buf the buffer to read from * @return the UUID from the buffer */ @@ -162,7 +155,6 @@ public enum ProtocolUtils { /** * Writes a list of {@link com.velocitypowered.api.util.GameProfile.Property} to the buffer. - * * @param buf the buffer to write to * @param properties the properties to serialize */ @@ -183,7 +175,6 @@ public enum ProtocolUtils { /** * Reads a list of {@link com.velocitypowered.api.util.GameProfile.Property} from the buffer. - * * @param buf the buffer to read from * @return the read properties */ From fd367c6efdc95562739e5603070ba454e27822d9 Mon Sep 17 00:00:00 2001 From: Leymooo Date: Wed, 4 Sep 2019 01:43:25 +0300 Subject: [PATCH 12/14] Add method to determine if player is in OnlineMode --- .../java/com/velocitypowered/api/proxy/Player.java | 7 +++++++ .../proxy/connection/client/ConnectedPlayer.java | 11 +++++++++-- .../proxy/connection/client/LoginSessionHandler.java | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) 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 54fcc8d99..b2ef61409 100644 --- a/api/src/main/java/com/velocitypowered/api/proxy/Player.java +++ b/api/src/main/java/com/velocitypowered/api/proxy/Player.java @@ -65,6 +65,13 @@ public interface Player extends CommandSource, InboundConnection, ChannelMessage */ long getPing(); + /** + * Returns the player's connection status. + * + * @return true if the player is authenticated with Mojang servers + */ + boolean isOnlineMode(); + /** * Sends a chat message to the player's client. * 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 d1a609023..c012e8fcb 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 @@ -90,6 +90,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { private PermissionFunction permissionFunction; private int tryIndex = 0; private long ping = -1; + private final boolean onlineMode; private @Nullable VelocityServerConnection connectedServer; private @Nullable VelocityServerConnection connectionInFlight; private @Nullable PlayerSettings settings; @@ -102,8 +103,8 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { private @MonotonicNonNull List serversToTry = null; - ConnectedPlayer(VelocityServer server, GameProfile profile, - MinecraftConnection connection, @Nullable InetSocketAddress virtualHost) { + ConnectedPlayer(VelocityServer server, GameProfile profile, MinecraftConnection connection, + @Nullable InetSocketAddress virtualHost, boolean onlineMode) { this.server = server; if (connection.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { this.tabList = new VelocityTabList(connection); @@ -116,6 +117,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { this.permissionFunction = PermissionFunction.ALWAYS_UNDEFINED; this.connectionPhase = connection.getType().getInitialClientPhase(); this.knownChannels = CappedSet.create(MAX_PLUGIN_CHANNELS); + this.onlineMode = onlineMode; } @Override @@ -151,6 +153,11 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { this.ping = ping; } + @Override + public boolean isOnlineMode() { + return onlineMode; + } + @Override public PlayerSettings getPlayerSettings() { return settings == null ? ClientSettingsWrapper.DEFAULT : this.settings; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java index 444232869..05b032ce6 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/LoginSessionHandler.java @@ -232,7 +232,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler { // Initiate a regular connection and move over to it. ConnectedPlayer player = new ConnectedPlayer(server, profileEvent.getGameProfile(), mcConnection, - inbound.getVirtualHost().orElse(null)); + inbound.getVirtualHost().orElse(null), onlineMode); this.connectedPlayer = player; if (!server.canRegisterConnection(player)) { player.disconnect(VelocityMessages.ALREADY_CONNECTED); From aef0f2ca8c0aa37683eea3f30c9a5cd72456de38 Mon Sep 17 00:00:00 2001 From: Gabik21 Date: Thu, 5 Sep 2019 12:17:19 +0200 Subject: [PATCH 13/14] Fix name mapping not being cleared on switch This fixes a bug where tablist would be messed up for 1.7 clients due to an internal misconception. --- .../com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java | 1 + 1 file changed, 1 insertion(+) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java index 31b494545..b1e5c2610 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/tablist/VelocityTabListLegacy.java @@ -52,6 +52,7 @@ public class VelocityTabListLegacy extends VelocityTabList { Collections.singletonList(PlayerListItem.Item.from(value)))); } entries.clear(); + nameMapping.clear(); } @Override From 3a77068088677cca6f1d50b13f75dbdabfd123ef Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 7 Sep 2019 00:15:10 -0400 Subject: [PATCH 14/14] Slightly more accurate natives check --- .../velocitypowered/natives/encryption/JavaVelocityCipher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java b/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java index 88f7fa921..5382da898 100644 --- a/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java +++ b/native/src/main/java/com/velocitypowered/natives/encryption/JavaVelocityCipher.java @@ -67,7 +67,7 @@ public class JavaVelocityCipher implements VelocityCipher { } private static ByteBuf toHeap(ByteBuf src) { - if (!src.isDirect()) { + if (src.hasArray()) { return src.retain(); }