From a3c4522ca0409cc1915bcdc3e62a2368cabba491 Mon Sep 17 00:00:00 2001 From: Slava Maspanov Date: Sat, 25 Aug 2018 03:55:15 +0300 Subject: [PATCH] Allow to enable online mode for player connection (#51) --- .gitignore | 3 + .../api/event/ResultedEvent.java | 3 +- .../api/event/connection/PreLoginEvent.java | 68 +++++++++++++++-- .../gameprofile/GameProfileRequestEvent.java | 53 +++++++++++++ .../com/velocitypowered/api/proxy/Player.java | 3 + .../velocitypowered/api/util/GameProfile.java | 2 +- .../connection/client/ConnectedPlayer.java | 4 +- .../client/LoginSessionHandler.java | 76 +++++++++++-------- 8 files changed, 174 insertions(+), 38 deletions(-) create mode 100644 api/src/main/java/com/velocitypowered/api/event/player/gameprofile/GameProfileRequestEvent.java diff --git a/.gitignore b/.gitignore index 6b39e43d9..fd8f6bff5 100644 --- a/.gitignore +++ b/.gitignore @@ -92,6 +92,9 @@ modules.xml **/.settings/ **/bin/ +# NetBeans Gradle# +.nb-gradle/ + # Mobile Tools for Java (J2ME) .mtj.tmp/ diff --git a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java index 04f28f390..28bc71c2b 100644 --- a/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/ResultedEvent.java @@ -1,6 +1,7 @@ package com.velocitypowered.api.event; import com.google.common.base.Preconditions; + import net.kyori.text.Component; import net.kyori.text.serializer.ComponentSerializers; import org.checkerframework.checker.nullness.qual.NonNull; @@ -72,7 +73,7 @@ public interface ResultedEvent { private final boolean allowed; private final @Nullable Component reason; - private ComponentResult(boolean allowed, @Nullable Component reason) { + protected ComponentResult(boolean allowed, @Nullable Component reason) { this.allowed = allowed; this.reason = reason; } diff --git a/api/src/main/java/com/velocitypowered/api/event/connection/PreLoginEvent.java b/api/src/main/java/com/velocitypowered/api/event/connection/PreLoginEvent.java index ad0c9c4a3..9c052df96 100644 --- a/api/src/main/java/com/velocitypowered/api/event/connection/PreLoginEvent.java +++ b/api/src/main/java/com/velocitypowered/api/event/connection/PreLoginEvent.java @@ -2,22 +2,28 @@ package com.velocitypowered.api.event.connection; import com.google.common.base.Preconditions; import com.velocitypowered.api.event.ResultedEvent; +import com.velocitypowered.api.event.ResultedEvent.ComponentResult; import com.velocitypowered.api.proxy.InboundConnection; + +import net.kyori.text.Component; + + import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; /** * This event is fired when a player has initiated a connection with the proxy but before the proxy authenticates the * player with Mojang or before the player's proxy connection is fully established (for offline mode). */ -public class PreLoginEvent implements ResultedEvent { +public class PreLoginEvent implements ResultedEvent { private final InboundConnection connection; private final String username; - private ComponentResult result; + private PreLoginComponentResult result; public PreLoginEvent(InboundConnection connection, String username) { this.connection = Preconditions.checkNotNull(connection, "connection"); this.username = Preconditions.checkNotNull(username, "username"); - this.result = ComponentResult.allowed(); + this.result = PreLoginComponentResult.allowed(); } public InboundConnection getConnection() { @@ -29,12 +35,12 @@ public class PreLoginEvent implements ResultedEvent { logger.error("Unable to enable encryption", exception); @@ -125,20 +127,24 @@ public class LoginSessionHandler implements MinecraftSessionHandler { PreLoginEvent event = new PreLoginEvent(apiInbound, login.getUsername()); VelocityServer.getServer().getEventManager().fire(event) .thenRunAsync(() -> { - if (!event.getResult().isAllowed()) { + if (inbound.isClosed()) { + // The player was disconnected + return; + } + PreLoginComponentResult result = event.getResult(); + if (!result.isAllowed()) { // The component is guaranteed to be provided if the connection was denied. inbound.closeWith(Disconnect.create(event.getResult().getReason().get())); return; } - - if (VelocityServer.getServer().getConfiguration().isOnlineMode()) { + + if (VelocityServer.getServer().getConfiguration().isOnlineMode() || result.isOnlineModeAllowed()) { // Request encryption. EncryptionRequest request = generateRequest(); this.verify = Arrays.copyOf(request.getVerifyToken(), 4); inbound.write(request); } else { - // Offline-mode, don't try to request encryption. - initializePlayer(GameProfile.forOfflinePlayer(login.getUsername())); + initializePlayer(GameProfile.forOfflinePlayer(login.getUsername()), false); } }, inbound.getChannel().eventLoop()); } @@ -153,28 +159,38 @@ public class LoginSessionHandler implements MinecraftSessionHandler { return request; } - private void initializePlayer(GameProfile profile) { - // Initiate a regular connection and move over to it. - ConnectedPlayer player = new ConnectedPlayer(profile, inbound, apiInbound.getVirtualHost().orElse(null)); + private void initializePlayer(GameProfile profile, boolean onlineMode) { - // load permissions first - VelocityServer.getServer().getEventManager().fire(new PermissionsSetupEvent(player, ConnectedPlayer.DEFAULT_PERMISSIONS)) - .thenCompose(event -> { - // wait for permissions to load, then set the players permission function - player.setPermissionFunction(event.createFunction(player)); - // then call & wait for the login event - return VelocityServer.getServer().getEventManager().fire(new LoginEvent(player)); - }) - // then complete the connection - .thenAcceptAsync(event -> { - if (!event.getResult().isAllowed()) { - // The component is guaranteed to be provided if the connection was denied. - inbound.closeWith(Disconnect.create(event.getResult().getReason().get())); - return; - } + GameProfileRequestEvent profileRequestEvent = new GameProfileRequestEvent(profile, onlineMode); + + VelocityServer.getServer().getEventManager().fire(profileRequestEvent).thenCompose(profileEvent -> { + // Initiate a regular connection and move over to it. + ConnectedPlayer player = new ConnectedPlayer(profileEvent.getGameProfile() == null ? profile : profileEvent.getGameProfile(), + inbound, apiInbound.getVirtualHost().orElse(null)); + + return VelocityServer.getServer().getEventManager().fire(new PermissionsSetupEvent(player, ConnectedPlayer.DEFAULT_PERMISSIONS)) + .thenCompose(event -> { + // wait for permissions to load, then set the players permission function + player.setPermissionFunction(event.createFunction(player)); + // then call & wait for the login event + return VelocityServer.getServer().getEventManager().fire(new LoginEvent(player)); + }) + // then complete the connection + .thenAcceptAsync(event -> { + if (inbound.isClosed()) { + // The player was disconnected + return; + } + if (!event.getResult().isAllowed()) { + // The component is guaranteed to be provided if the connection was denied. + inbound.closeWith(Disconnect.create(event.getResult().getReason().get())); + return; + } + + handleProxyLogin(player); + }, inbound.getChannel().eventLoop()); + }); - handleProxyLogin(player); - }, inbound.getChannel().eventLoop()); } private void handleProxyLogin(ConnectedPlayer player) {