Allow to enable online mode for player connection (#51)

This commit is contained in:
Slava Maspanov
2018-08-25 03:55:15 +03:00
committed by Andrew Steinborn
parent e6e3ccaa95
commit a3c4522ca0
8 changed files with 174 additions and 38 deletions

View File

@@ -9,12 +9,14 @@ import com.velocitypowered.api.proxy.ConnectionRequestBuilder;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
import com.velocitypowered.api.util.MessagePosition;
import com.velocitypowered.api.util.UuidUtils;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
import com.velocitypowered.proxy.connection.util.ConnectionMessages;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.Chat;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
@@ -45,9 +47,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
private static final Logger logger = LogManager.getLogger(ConnectedPlayer.class);
private final GameProfile profile;
private final MinecraftConnection connection;
private final InetSocketAddress virtualHost;
private final GameProfile profile;
private PermissionFunction permissionFunction = null;
private int tryIndex = 0;
private VelocityServerConnection connectedServer;

View File

@@ -3,11 +3,14 @@ package com.velocitypowered.proxy.connection.client;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.event.connection.LoginEvent;
import com.velocitypowered.api.event.connection.PreLoginEvent;
import com.velocitypowered.api.event.connection.PreLoginEvent.PreLoginComponentResult;
import com.velocitypowered.api.event.permission.PermissionsSetupEvent;
import com.velocitypowered.api.event.player.gameprofile.GameProfileRequestEvent;
import com.velocitypowered.api.proxy.InboundConnection;
import com.velocitypowered.api.server.ServerInfo;
import com.velocitypowered.proxy.connection.VelocityConstants;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.api.util.UuidUtils;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolConstants;
import com.velocitypowered.proxy.protocol.StateRegistry;
@@ -37,7 +40,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
private static final Logger logger = LogManager.getLogger(LoginSessionHandler.class);
private static final String MOJANG_SERVER_AUTH_URL =
"https://sessionserver.mojang.com/session/minecraft/hasJoined?username=%s&serverId=%s&ip=%s";
private final MinecraftConnection inbound;
private final InboundConnection apiInbound;
private ServerLogin login;
@@ -97,15 +100,14 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
// The player disconnected after we authenticated them.
return;
}
try {
inbound.enableEncryption(decryptedSharedSecret);
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
}
GameProfile profile = VelocityServer.GSON.fromJson(profileResponse, GameProfile.class);
initializePlayer(profile);
initializePlayer(VelocityServer.GSON.fromJson(profileResponse, GameProfile.class), true);
}, inbound.getChannel().eventLoop())
.exceptionally(exception -> {
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) {