public override async Task Process(LoginPacket packet, IPacketContext context)
        {
            var identityResult = await UserManager.AddLoginAsync(packet.Username, packet.Password);

            var errors      = (identityResult.Errors != null) ? identityResult.Errors.ToArray() : new string[0];
            var replyPacket = new LoginReplyPacket(identityResult.Success, errors);

            context.Sender.Send(replyPacket);

            if (replyPacket.Accepted)
            {
                var user = await UserManager.UserStorage.FindByNameAsync(packet.Username);

                var userConnection = TcpConnections.FindByEndpoint(context.Sender.EndPoint);
                userConnection.UserTag = user;

                NetPeer.OnClientConnected(user);

                this.NetPeer.Logger.LogInformation("User '{username}' authenticated ({address}).",
                                                   packet.Username, context.Sender.EndPoint.ToString());
            }
            else
            {
                this.NetPeer.Logger.LogInformation("User '{username}' failed to authenticated ({address}).",
                                                   packet.Username, context.Sender.EndPoint.ToString());
            }
        }
        public override Task Process(ChatPacket packet, IPacketContext context)
        {
            var sender = tcpConnections.FindByEndpoint(context.Sender.EndPoint);
            var user   = (TUser)sender.UserTag;

            this.netPeer.SendPacket(new ChatReplyPacket(Guid.NewGuid(), packet.Message));

            var message = new ChatMessage(user, packet.Channel, packet.Message);

            chatService.InvokeReceived(message);

            return(Task.CompletedTask);
        }