//Login.
        private static async Task LoginStartHandler(byte[] data, MemoryStream stream, MinecraftClientConnection connection)
        {
            Logger.LogMessage("Login Start");

            //Grab username.
            connection.connectingUsername = await ReadStringAsync(stream);

            if (connection.config.OfflineMode)
            {
                connection.WriteString(GetKickMessage(await AuthenticationManager.GenerateToken(connection.connectingUsername, true)));
                connection.Flush(0);

                connection.client.Close();
                return;
            }

            //Generate encryption data needed for connection.
            connection.encryptionState = new FakeServerEncryptionState();
            connection.encryptionState.GenerateKeyPair();
            var keyTokenPair = connection.encryptionState.GeneratePublicKeyAndToken();

            connection.randomToken = keyTokenPair.randomToken;

            //Server ID (useless)
            connection.WriteString("");
            //Public Key.
            connection.WriteVarInt(keyTokenPair.publicKey.Length);
            connection.Write(keyTokenPair.publicKey);
            //Token.
            connection.WriteVarInt(keyTokenPair.randomToken.Length);
            connection.Write(keyTokenPair.randomToken);

            connection.Flush(1);
        }
        //Status.
        private static async Task StatusRequestHandler(byte[] data, MemoryStream stream, MinecraftClientConnection connection)
        {
            Logger.LogMessage("Status Request");

            connection.WriteString(serverStatusResponse);
            connection.Flush(0);
        }
        private static async Task ServerAuthRequestHandler(byte[] data, MemoryStream stream, MinecraftClientConnection connection)
        {
            Logger.LogMessage("Server Auth Request");

            //Read secret.
            int secretLength = await ReadVarIntAsync(stream);

            byte[] secret = new byte[secretLength];
            ReadBytesAsync(stream, secret).Wait();

            //Verify token.
            int encryptedTokenLength = await ReadVarIntAsync(stream);

            byte[] encryptedToken = new byte[encryptedTokenLength];
            ReadBytesAsync(stream, encryptedToken).Wait();

            //Decrypt shared key from secret.
            connection.sharedKey = connection.encryptionState.Decrypt(secret);
            //Decrypt the token.
            byte[] token = connection.encryptionState.Decrypt(encryptedToken);

            if (!token.SequenceEqual(connection.randomToken))
            {
                //Failed to verify token.
                //Close connection.
                connection.isRunning = false;
                return;
            }

            //Get the ID of the server the client joined, from the public key.
            string serverID = MinecraftShaDigest(connection.sharedKey.Concat(connection.encryptionState.publicKey).ToArray());

            //Verify the player has joined the server they say they have, using Mojang's auth.
            FiguraAuthServer.JoinedResponse hasJoinedResponse = await FiguraAuthServer.HasJoined(connection.connectingUsername, serverID);

            if (hasJoinedResponse == null)
            {
                //Player hasn't actually joined this server, auth failed, close connection.
                connection.isRunning = false;
                return;
            }

            //Auth success!!!
            Logger.LogMessage("Auth Complete for user " + connection.connectingUsername);

            //Turn on encryption
            connection.enableEncryption = true;

            //Respond with JWT in kick message.
            connection.WriteString(GetKickMessage(await AuthenticationManager.GenerateToken(connection.connectingUsername, false)));
            connection.Flush(0);

            connection.client.Close();
        }
        private static async Task PingRequestHandler(byte[] data, MemoryStream stream, MinecraftClientConnection connection)
        {
            Logger.LogMessage("Ping Request");

            long l = BitConverter.ToInt64(data, 0);

            connection.WriteLong(l);
            connection.Flush(1);

            connection.client.Close();
        }