mirror of https://github.com/Minestom/Minestom.git
105 lines
4.9 KiB
Java
105 lines
4.9 KiB
Java
package net.minestom.server.network.packet.client.login;
|
|
|
|
import net.kyori.adventure.text.Component;
|
|
import net.kyori.adventure.text.format.NamedTextColor;
|
|
import net.minestom.server.Configuration;
|
|
import net.minestom.server.MinecraftServer;
|
|
import net.minestom.server.crypto.PlayerPublicKey;
|
|
import net.minestom.server.entity.Player;
|
|
import net.minestom.server.extras.MojangAuth;
|
|
import net.minestom.server.extras.bungee.BungeeCordProxy;
|
|
import net.minestom.server.extras.velocity.VelocityProxy;
|
|
import net.minestom.server.network.ConnectionState;
|
|
import net.minestom.server.network.packet.client.ClientPreplayPacket;
|
|
import net.minestom.server.network.packet.server.login.EncryptionRequestPacket;
|
|
import net.minestom.server.network.packet.server.login.LoginDisconnectPacket;
|
|
import net.minestom.server.network.packet.server.login.LoginPluginRequestPacket;
|
|
import net.minestom.server.network.player.PlayerConnection;
|
|
import net.minestom.server.network.player.PlayerSocketConnection;
|
|
import net.minestom.server.utils.binary.BinaryReader;
|
|
import net.minestom.server.utils.binary.BinaryWriter;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import java.util.UUID;
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
|
|
public record LoginStartPacket(@NotNull String username, @Nullable PlayerPublicKey publicKey) implements ClientPreplayPacket {
|
|
private static final Component ALREADY_CONNECTED = Component.text("You are already on this server", NamedTextColor.RED);
|
|
|
|
public LoginStartPacket(BinaryReader reader) {
|
|
this(reader.readSizedString(16), reader.readBoolean() ?
|
|
new PlayerPublicKey(reader) : null);
|
|
}
|
|
|
|
@Override
|
|
public void process(@NotNull PlayerConnection connection) {
|
|
connection.setPlayerPublicKey(publicKey);
|
|
final Configuration config = MinecraftServer.getConfiguration();
|
|
|
|
if (config.requireValidPlayerPublicKey()) {
|
|
if (publicKey != null) {
|
|
if (!publicKey.isValid()) {
|
|
connection.sendPacket(new LoginDisconnectPacket(config.invalidPlayerPublicKeyMessage()));
|
|
connection.disconnect();
|
|
}
|
|
} else {
|
|
connection.sendPacket(new LoginDisconnectPacket(config.missingPlayerPublicKeyMessage()));
|
|
connection.disconnect();
|
|
}
|
|
}
|
|
|
|
final boolean isSocketConnection = connection instanceof PlayerSocketConnection;
|
|
// Proxy support (only for socket clients) and cache the login username
|
|
if (isSocketConnection) {
|
|
PlayerSocketConnection socketConnection = (PlayerSocketConnection) connection;
|
|
socketConnection.UNSAFE_setLoginUsername(username);
|
|
// Velocity support
|
|
if (VelocityProxy.isEnabled()) {
|
|
final int messageId = ThreadLocalRandom.current().nextInt();
|
|
final String channel = VelocityProxy.PLAYER_INFO_CHANNEL;
|
|
// Important in order to retrieve the channel in the response packet
|
|
socketConnection.addPluginRequestEntry(messageId, channel);
|
|
connection.sendPacket(new LoginPluginRequestPacket(messageId, channel, null));
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (MojangAuth.isEnabled() && isSocketConnection) {
|
|
// Mojang auth
|
|
if (CONNECTION_MANAGER.getPlayer(username) != null) {
|
|
connection.sendPacket(new LoginDisconnectPacket(ALREADY_CONNECTED));
|
|
connection.disconnect();
|
|
return;
|
|
}
|
|
final PlayerSocketConnection socketConnection = (PlayerSocketConnection) connection;
|
|
socketConnection.setConnectionState(ConnectionState.LOGIN);
|
|
|
|
final byte[] publicKey = MojangAuth.getKeyPair().getPublic().getEncoded();
|
|
byte[] nonce = new byte[4];
|
|
ThreadLocalRandom.current().nextBytes(nonce);
|
|
socketConnection.setNonce(nonce);
|
|
socketConnection.sendPacket(new EncryptionRequestPacket("", publicKey, nonce));
|
|
} else {
|
|
final boolean bungee = BungeeCordProxy.isEnabled();
|
|
// Offline
|
|
final UUID playerUuid = bungee && isSocketConnection ?
|
|
((PlayerSocketConnection) connection).getBungeeUuid() :
|
|
CONNECTION_MANAGER.getPlayerConnectionUuid(connection, username);
|
|
|
|
Player player = CONNECTION_MANAGER.startPlayState(connection, playerUuid, username, true);
|
|
if (bungee && isSocketConnection) {
|
|
player.setSkin(((PlayerSocketConnection) connection).getBungeeSkin());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void write(@NotNull BinaryWriter writer) {
|
|
if (username.length() > 16)
|
|
throw new IllegalArgumentException("Username is not allowed to be longer than 16 characters");
|
|
writer.writeSizedString(username);
|
|
writer.writeNullable(publicKey);
|
|
}
|
|
}
|