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 95cbdefb8..0dab89357 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 @@ -104,6 +104,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { private final CompletableFuture teardownFuture = new CompletableFuture<>(); private @MonotonicNonNull List serversToTry = null; + private boolean explicitlyDisconnected = false; ConnectedPlayer(VelocityServer server, GameProfile profile, MinecraftConnection connection, @Nullable InetSocketAddress virtualHost, boolean onlineMode) { @@ -281,9 +282,25 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { @Override public void disconnect(Component reason) { + if (connection.eventLoop().inEventLoop()) { + disconnect0(reason, false); + } else { + connection.eventLoop().execute(() -> disconnect0(reason, false)); + } + } + + /** + * Disconnects the player from the proxy. + * @param reason the reason for disconnecting the player + * @param duringLogin whether the disconnect happened during login + */ + public void disconnect0(Component reason, boolean duringLogin) { logger.info("{} has disconnected: {}", this, LegacyComponentSerializer.legacy().serialize(reason)); + this.explicitlyDisconnected = true; connection.closeWith(Disconnect.create(reason)); + + server.getEventManager().fireAndForget(new DisconnectEvent(this, duringLogin)); } @Override @@ -574,10 +591,13 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { connectedServer.disconnect(); } boolean isConnected = server.getPlayer(this.getUniqueId()).isPresent(); - server.unregisterConnection(this); - server.getEventManager().fire(new DisconnectEvent(this, !isConnected)) - .thenRun(() -> this.teardownFuture.complete(null)); + if (!this.explicitlyDisconnected) { + server.getEventManager().fire(new DisconnectEvent(this, !isConnected)) + .thenRun(() -> this.teardownFuture.complete(null)); + } else { + this.teardownFuture.complete(null); + } } public CompletableFuture getTeardownFuture() { 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 380fd9831..831304d2b 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 @@ -204,7 +204,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler { inbound.getVirtualHost().orElse(null), onlineMode); this.connectedPlayer = player; if (!server.canRegisterConnection(player)) { - player.disconnect(VelocityMessages.ALREADY_CONNECTED); + player.disconnect0(VelocityMessages.ALREADY_CONNECTED, true); return CompletableFuture.completedFuture(null); } @@ -246,10 +246,10 @@ public class LoginSessionHandler implements MinecraftSessionHandler { Optional reason = event.getResult().getReason(); if (reason.isPresent()) { - player.disconnect(reason.get()); + player.disconnect0(reason.get(), true); } else { if (!server.registerConnection(player)) { - player.disconnect(VelocityMessages.ALREADY_CONNECTED); + player.disconnect0(VelocityMessages.ALREADY_CONNECTED, true); return; } @@ -269,7 +269,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler { .thenRunAsync(() -> { Optional toTry = event.getInitialServer(); if (!toTry.isPresent()) { - player.disconnect(VelocityMessages.NO_AVAILABLE_SERVERS); + player.disconnect0(VelocityMessages.NO_AVAILABLE_SERVERS, true); return; } player.createConnectionRequest(toTry.get()).fireAndForget(); 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 5db35433c..30bf616a0 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 @@ -14,6 +14,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class TabCompleteRequest implements MinecraftPacket { + private static final int VANILLA_MAX_TAB_COMPLETE_LEN = 2048; + private @Nullable String command; private int transactionId; private boolean assumeCommand; @@ -78,9 +80,9 @@ public class TabCompleteRequest implements MinecraftPacket { public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { if (version.compareTo(MINECRAFT_1_13) >= 0) { this.transactionId = ProtocolUtils.readVarInt(buf); - this.command = ProtocolUtils.readString(buf, Chat.MAX_SERVERBOUND_MESSAGE_LENGTH); + this.command = ProtocolUtils.readString(buf, VANILLA_MAX_TAB_COMPLETE_LEN); } else { - this.command = ProtocolUtils.readString(buf, Chat.MAX_SERVERBOUND_MESSAGE_LENGTH); + this.command = ProtocolUtils.readString(buf, VANILLA_MAX_TAB_COMPLETE_LEN); if (version.compareTo(MINECRAFT_1_9) >= 0) { this.assumeCommand = buf.readBoolean(); }