From 12f5bdfc48ee7f2300c79f728e9aacc8f8bda9f0 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Fri, 15 Feb 2019 15:07:38 -0500 Subject: [PATCH] Properly implement fallback support. --- .../event/player/KickedFromServerEvent.java | 19 +++++ .../connection/client/ConnectedPlayer.java | 80 ++++++++++++------- .../proxy/util/VelocityMessages.java | 2 + 3 files changed, 74 insertions(+), 27 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java b/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java index ce55ae353..87ae8c3f0 100644 --- a/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/player/KickedFromServerEvent.java @@ -41,6 +41,25 @@ public final class KickedFromServerEvent implements this.result = new Notify(fancyReason); } + /** + * Creates a {@code KickedFromServerEvent} instance. + * @param player the player affected + * @param server the server the player disconnected from + * @param originalReason the reason for being kicked, optional + * @param duringServerConnect whether or not the player was kicked during the connection process + * @param result the initial result + */ + public KickedFromServerEvent(Player player, + RegisteredServer server, + @Nullable Component originalReason, boolean duringServerConnect, + ServerKickResult result) { + this.player = Preconditions.checkNotNull(player, "player"); + this.server = Preconditions.checkNotNull(server, "server"); + this.originalReason = originalReason; + this.duringServerConnect = duringServerConnect; + this.result = Preconditions.checkNotNull(result, "result"); + } + @Override public ServerKickResult getResult() { return result; 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 9265be3e4..0ab45a4f3 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 @@ -7,6 +7,7 @@ import com.velocitypowered.api.event.player.KickedFromServerEvent; import com.velocitypowered.api.event.player.KickedFromServerEvent.DisconnectPlayer; import com.velocitypowered.api.event.player.KickedFromServerEvent.Notify; import com.velocitypowered.api.event.player.KickedFromServerEvent.RedirectPlayer; +import com.velocitypowered.api.event.player.KickedFromServerEvent.ServerKickResult; import com.velocitypowered.api.event.player.PlayerModInfoEvent; import com.velocitypowered.api.event.player.PlayerSettingsChangedEvent; import com.velocitypowered.api.event.player.ServerPreConnectEvent; @@ -42,6 +43,7 @@ import com.velocitypowered.proxy.protocol.packet.ResourcePackRequest; import com.velocitypowered.proxy.protocol.packet.TitlePacket; import com.velocitypowered.proxy.server.VelocityRegisteredServer; import com.velocitypowered.proxy.tablist.VelocityTabList; +import com.velocitypowered.proxy.util.VelocityMessages; import io.netty.buffer.ByteBufUtil; import java.net.InetSocketAddress; import java.util.Collections; @@ -367,31 +369,53 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { disconnect(friendlyReason); } } else { + boolean kickedFromCurrent = connectedServer.getServer().equals(rs); + ServerKickResult result; + if (kickedFromCurrent) { + Optional next = getNextServerToTry(); + result = next.map(RedirectPlayer::create) + .orElseGet(() -> DisconnectPlayer.create(friendlyReason)); + } else { + result = Notify.create(friendlyReason); + } KickedFromServerEvent originalEvent = new KickedFromServerEvent(this, rs, kickReason, - !connectedServer.getServer().equals(rs), friendlyReason); - server.getEventManager().fire(originalEvent) - .thenAcceptAsync(event -> { - if (event.getResult() instanceof DisconnectPlayer) { - DisconnectPlayer res = (DisconnectPlayer) event.getResult(); - disconnect(res.getReason()); - } else if (event.getResult() instanceof RedirectPlayer) { - RedirectPlayer res = (RedirectPlayer) event.getResult(); - createConnectionRequest(res.getServer()).fireAndForget(); - } else if (event.getResult() instanceof Notify) { - Notify res = (Notify) event.getResult(); - if (event.kickedDuringServerConnect()) { - sendMessage(res.getMessage()); - } else { - disconnect(res.getMessage()); - } - } else { - // In case someone gets creative, assume we want to disconnect the player. - disconnect(friendlyReason); - } - }, minecraftConnection.eventLoop()); + !kickedFromCurrent, result); + handleKickEvent(originalEvent, friendlyReason); } } + private void handleKickEvent(KickedFromServerEvent originalEvent, + Component friendlyReason) { + server.getEventManager().fire(originalEvent) + .thenAcceptAsync(event -> { + if (event.getResult() instanceof DisconnectPlayer) { + DisconnectPlayer res = (DisconnectPlayer) event.getResult(); + disconnect(res.getReason()); + } else if (event.getResult() instanceof RedirectPlayer) { + RedirectPlayer res = (RedirectPlayer) event.getResult(); + createConnectionRequest(res.getServer()) + .connectWithIndication() + .whenCompleteAsync((newResult, exception) -> { + if (newResult == null || !newResult) { + disconnect(friendlyReason); + } else { + sendMessage(VelocityMessages.MOVED_TO_NEW_SERVER); + } + }, minecraftConnection.eventLoop()); + } else if (event.getResult() instanceof Notify) { + Notify res = (Notify) event.getResult(); + if (event.kickedDuringServerConnect()) { + sendMessage(res.getMessage()); + } else { + disconnect(res.getMessage()); + } + } else { + // In case someone gets creative, assume we want to disconnect the player. + disconnect(friendlyReason); + } + }, minecraftConnection.eventLoop()); + } + /** * Finds another server to attempt to log into, if we were unexpectedly disconnected from the * server. @@ -408,13 +432,15 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player { serversToTry = server.getConfiguration().getAttemptConnectionOrder(); } - if (tryIndex >= serversToTry.size()) { - return Optional.empty(); - } + for (; tryIndex < serversToTry.size(); tryIndex++) { + String toTryName = serversToTry.get(tryIndex); + if (connectedServer != null && toTryName.equals(connectedServer.getServerInfo().getName())) { + continue; + } - String toTryName = serversToTry.get(tryIndex); - tryIndex++; - return server.getServer(toTryName); + return server.getServer(toTryName); + } + return Optional.empty(); } /** diff --git a/proxy/src/main/java/com/velocitypowered/proxy/util/VelocityMessages.java b/proxy/src/main/java/com/velocitypowered/proxy/util/VelocityMessages.java index 621003e4c..f88defb22 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/util/VelocityMessages.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/util/VelocityMessages.java @@ -14,6 +14,8 @@ public class VelocityMessages { .of("No available servers", TextColor.RED); public static final Component ALREADY_CONNECTED = TextComponent .of("You are already connected to this proxy!", TextColor.RED); + public static final Component MOVED_TO_NEW_SERVER = TextComponent + .of("You were moved from the server you were on because you were kicked", TextColor.RED); private VelocityMessages() { throw new AssertionError();