From 1938013ab213c0fbfc0c9ed0e3ba093ce04f3acb Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Mon, 29 Jun 2020 11:17:08 -0400 Subject: [PATCH 1/7] Make DisconnectEvent more sane This is a step towards fixing #289 and removing some less-than-optimal behavior in plugins I maintain internally. --- .../api/event/connection/DisconnectEvent.java | 30 ++++++++++++++++--- .../proxy/connection/MinecraftConnection.java | 4 +++ .../connection/client/ConnectedPlayer.java | 18 +++++++++-- .../client/LoginSessionHandler.java | 8 +++-- 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java index 2442077a8..fbbb7b5ac 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java @@ -1,5 +1,8 @@ package com.velocitypowered.api.event.connection; +import static com.velocitypowered.api.event.connection.DisconnectEvent.LoginStatus.CANCELLED_BY_PROXY; +import static com.velocitypowered.api.event.connection.DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN; + import com.google.common.base.Preconditions; import com.velocitypowered.api.proxy.Player; @@ -10,31 +13,50 @@ import com.velocitypowered.api.proxy.Player; public final class DisconnectEvent { private final Player player; - private final boolean disconnectedDuringLogin; + private final LoginStatus loginStatus; + @Deprecated public DisconnectEvent(Player player) { this(player, false); } + @Deprecated public DisconnectEvent(Player player, boolean disconnectedDuringLogin) { + this(player, disconnectedDuringLogin ? CANCELLED_BY_PROXY : SUCCESSFUL_LOGIN); + } + + public DisconnectEvent(Player player, LoginStatus loginStatus) { this.player = Preconditions.checkNotNull(player, "player"); - this.disconnectedDuringLogin = disconnectedDuringLogin; + this.loginStatus = Preconditions.checkNotNull(loginStatus, "loginStatus"); } public Player getPlayer() { return player; } + @Deprecated public boolean disconnectedDuringLogin() { - return this.disconnectedDuringLogin; + return this.loginStatus == CANCELLED_BY_PROXY; + } + + public LoginStatus getLoginStatus() { + return loginStatus; } @Override public String toString() { return "DisconnectEvent{" + "player=" + player + ", " - + "disconnectedDuringLogin=" + disconnectedDuringLogin + + "loginStatus=" + loginStatus + '}'; } + + public enum LoginStatus { + + SUCCESSFUL_LOGIN, + CONFLICTING_LOGIN, + CANCELLED_BY_USER, + CANCELLED_BY_PROXY + } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java index ecf8c87c3..8966e8bc4 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java @@ -271,6 +271,10 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { return channel.config().isAutoRead(); } + public boolean isKnownDisconnect() { + return knownDisconnect; + } + /** * Determines whether or not the channel should continue reading data automaticaly. * @param autoReading whether or not we should read data automatically 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 27ba08d0c..86a2ce5ac 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 @@ -6,6 +6,7 @@ import static java.util.concurrent.CompletableFuture.completedFuture; import com.google.common.base.Preconditions; import com.google.gson.JsonObject; import com.velocitypowered.api.event.connection.DisconnectEvent; +import com.velocitypowered.api.event.connection.DisconnectEvent.LoginStatus; import com.velocitypowered.api.event.player.KickedFromServerEvent; import com.velocitypowered.api.event.player.KickedFromServerEvent.DisconnectPlayer; import com.velocitypowered.api.event.player.KickedFromServerEvent.Notify; @@ -586,10 +587,21 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { if (connectedServer != null) { connectedServer.disconnect(); } - boolean isConnected = server.getPlayer(this.getUniqueId()).isPresent(); + + Optional connectedPlayer = server.getPlayer(this.getUniqueId()); server.unregisterConnection(this); - server.getEventManager().fire(new DisconnectEvent(this, !isConnected)) - .thenRun(() -> this.teardownFuture.complete(null)); + + DisconnectEvent.LoginStatus status; + if (connectedPlayer.isPresent()) { + status = connectedPlayer.get() == this ? LoginStatus.SUCCESSFUL_LOGIN + : LoginStatus.CONFLICTING_LOGIN; + } else { + status = connection.isKnownDisconnect() ? LoginStatus.CANCELLED_BY_PROXY : + LoginStatus.CANCELLED_BY_USER; + } + + DisconnectEvent event = new DisconnectEvent(this, status); + server.getEventManager().fire(event).thenRun(() -> 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 2f185652b..7483bb076 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 @@ -202,10 +202,14 @@ public class LoginSessionHandler implements MinecraftSessionHandler { onlineMode); server.getEventManager().fire(profileRequestEvent).thenCompose(profileEvent -> { + if (mcConnection.isClosed()) { + // The player disconnected after we authenticated them. + return CompletableFuture.completedFuture(null); + } + // Initiate a regular connection and move over to it. ConnectedPlayer player = new ConnectedPlayer(server, profileEvent.getGameProfile(), - mcConnection, - inbound.getVirtualHost().orElse(null), onlineMode); + mcConnection, inbound.getVirtualHost().orElse(null), onlineMode); this.connectedPlayer = player; if (!server.canRegisterConnection(player)) { player.disconnect0(VelocityMessages.ALREADY_CONNECTED, true); From ea52cedfdfdb9ca05213e85a6a217764c46dc5ab Mon Sep 17 00:00:00 2001 From: Luck Date: Mon, 29 Jun 2020 15:48:28 +0100 Subject: [PATCH 2/7] Fire ProxyShutdownEvent before closing the scheduler / event bus Fixes #322 --- .../main/java/com/velocitypowered/proxy/VelocityServer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java index e011085a5..88b2e8971 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java @@ -403,6 +403,8 @@ public class VelocityServer implements ProxyServer { timedOut = true; } + eventManager.fireShutdownEvent(); + timedOut = !eventManager.shutdown() || timedOut; timedOut = !scheduler.shutdown() || timedOut; @@ -414,8 +416,6 @@ public class VelocityServer implements ProxyServer { Thread.currentThread().interrupt(); } - eventManager.fireShutdownEvent(); - shutdown = true; if (explicitExit) { From 801ae4f33db9f49444a901afb5c192e8d43e8d4d Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 3 Jul 2020 17:26:11 -0400 Subject: [PATCH 3/7] Add one more case to disconnectedDuringLogin() --- .../velocitypowered/api/event/connection/DisconnectEvent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java index fbbb7b5ac..77377e5c4 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java @@ -1,6 +1,7 @@ package com.velocitypowered.api.event.connection; import static com.velocitypowered.api.event.connection.DisconnectEvent.LoginStatus.CANCELLED_BY_PROXY; +import static com.velocitypowered.api.event.connection.DisconnectEvent.LoginStatus.CONFLICTING_LOGIN; import static com.velocitypowered.api.event.connection.DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN; import com.google.common.base.Preconditions; @@ -37,7 +38,7 @@ public final class DisconnectEvent { @Deprecated public boolean disconnectedDuringLogin() { - return this.loginStatus == CANCELLED_BY_PROXY; + return this.loginStatus == CANCELLED_BY_PROXY || this.loginStatus == CONFLICTING_LOGIN; } public LoginStatus getLoginStatus() { From 079b352c97596368762df333999498cf9c126d1f Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 3 Jul 2020 17:48:20 -0400 Subject: [PATCH 4/7] Add a new loginstatus for CANCELLED_BY_USER_BEFORE_COMPLETE --- .../api/event/connection/DisconnectEvent.java | 3 ++- .../proxy/connection/client/LoginSessionHandler.java | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java index 77377e5c4..85b5fae86 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/DisconnectEvent.java @@ -58,6 +58,7 @@ public final class DisconnectEvent { SUCCESSFUL_LOGIN, CONFLICTING_LOGIN, CANCELLED_BY_USER, - CANCELLED_BY_PROXY + CANCELLED_BY_PROXY, + CANCELLED_BY_USER_BEFORE_COMPLETE } } 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 7483bb076..134919be4 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 @@ -8,6 +8,8 @@ import static com.velocitypowered.proxy.util.EncryptionUtils.decryptRsa; import static com.velocitypowered.proxy.util.EncryptionUtils.generateServerId; import com.google.common.base.Preconditions; +import com.velocitypowered.api.event.connection.DisconnectEvent; +import com.velocitypowered.api.event.connection.DisconnectEvent.LoginStatus; import com.velocitypowered.api.event.connection.LoginEvent; import com.velocitypowered.api.event.connection.PostLoginEvent; import com.velocitypowered.api.event.connection.PreLoginEvent; @@ -224,13 +226,13 @@ public class LoginSessionHandler implements MinecraftSessionHandler { if (!mcConnection.isClosed()) { // wait for permissions to load, then set the players permission function player.setPermissionFunction(event.createFunction(player)); - finishLogin(player); + completeLoginProtocolPhaseAndInitialize(player); } }, mcConnection.eventLoop()); }); } - private void finishLogin(ConnectedPlayer player) { + private void completeLoginProtocolPhaseAndInitialize(ConnectedPlayer player) { int threshold = server.getConfiguration().getCompressionThreshold(); if (threshold >= 0 && mcConnection.getProtocolVersion().compareTo(MINECRAFT_1_8) >= 0) { mcConnection.write(new SetCompression(threshold)); @@ -253,6 +255,8 @@ public class LoginSessionHandler implements MinecraftSessionHandler { .thenAcceptAsync(event -> { if (mcConnection.isClosed()) { // The player was disconnected + server.getEventManager().fireAndForget(new DisconnectEvent(player, + LoginStatus.CANCELLED_BY_USER_BEFORE_COMPLETE)); return; } From 85d88d59d30ad53f8e3029379da0e96e886dc5fb Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 3 Jul 2020 19:16:55 -0400 Subject: [PATCH 5/7] Fix pinging being "delayed" on 1.7 --- .../proxy/connection/MinecraftConnection.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java index 8966e8bc4..c29ec7274 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java @@ -209,8 +209,10 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter { */ public void closeWith(Object msg) { if (channel.isActive()) { - if (channel.eventLoop().inEventLoop() - && this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) { + boolean is1Point8 = this.getProtocolVersion().compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0; + boolean isLegacyPing = this.getState() == StateRegistry.HANDSHAKE + || this.getState() == StateRegistry.STATUS; + if (channel.eventLoop().inEventLoop() && (is1Point8 || isLegacyPing)) { knownDisconnect = true; channel.writeAndFlush(msg).addListener(ChannelFutureListener.CLOSE); } else { From 4469a89aaab3058b123bd416b70b4f3b480dd48b Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 4 Jul 2020 03:19:38 -0400 Subject: [PATCH 6/7] Point all new Maven artifact deploys to Nexus --- api/build.gradle | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 245165348..4240658d0 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -92,10 +92,14 @@ publishing { repositories { maven { - name = 'myRepo' - def base = 'file:///maven-repo' - def releasesRepoUrl = "$base/releases" - def snapshotsRepoUrl = "$base/snapshots" + credentials { + username project.findProperty('nexusUsername') ?: '' + password project.findProperty('nexusPassword') ?: "" + } + name = 'velocity-nexus' + def base = 'https://nexus.velocitypowered.com/repository/velocity-artifacts' + def releasesRepoUrl = "$base-releases/" + def snapshotsRepoUrl = "$base-snapshots/" url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl } } From 81aed2cd1d5e67a7d6e3732d5285e0ab5828c612 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Sat, 4 Jul 2020 03:35:08 -0400 Subject: [PATCH 7/7] Get the Nexus credentials from the environment --- api/build.gradle | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/build.gradle b/api/build.gradle index 4240658d0..19d1f042e 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -93,9 +93,10 @@ publishing { repositories { maven { credentials { - username project.findProperty('nexusUsername') ?: '' - password project.findProperty('nexusPassword') ?: "" + username System.getenv("NEXUS_USERNAME") + password System.getenv("NEXUS_PASSWORD") } + name = 'velocity-nexus' def base = 'https://nexus.velocitypowered.com/repository/velocity-artifacts' def releasesRepoUrl = "$base-releases/"