/// <summary>Initializes the communication.</summary>
        /// <param name="clientPort">The client port.</param>
        private void InitializeCommunication(uint clientPort)
        {
            var msgClientHello = new ClientHelloMessage()
            {
                ClientId = ClientId, ClientPort = clientPort, Message = $"Hello from {ClientId}", Version = Shared.Constants.Version.PROTOCOL
            };
            UdpTransferFrame frame = new UdpTransferFrame(FrameType.ClientHello, msgClientHello.Serialize());

            ReliableMessaging.OnSendFrame(frame);
        }
        private void ProcessAuthenticationRequest(ServerAuthenticationRequest request, string signingKey)
        {
            var    offlineTokenProvider = new OfflineTokenProvider("", signingKey);
            string token = offlineTokenProvider.CreateJWTToken(request.AuthenticationChallenge, DateTime.UtcNow.AddMinutes(15));
            var    cmdClientAuthenticationResponse = new ClientAuthenticationResponse()
            {
                AuthenticationToken = token
            };

            ReliableMessaging.OnSendFrame(new UdpTransferFrame(FrameType.ClientAuthenticationResponse, cmdClientAuthenticationResponse.Serialize()));
        }
        /// <summary>Processes the UDP transfer frame.</summary>
        /// <param name="frame">The frame.</param>
        private void ProcessUdpTransferFrame(UdpTransferFrame frame)
        {
            switch (frame.Type)
            {
            case FrameType.ServerAuthenticationRequest:
                var msgAuthenticationRequest = new ServerAuthenticationRequest(frame.MessageBuffer);
                ProcessAuthenticationRequest(msgAuthenticationRequest, this.signingKeyBase64);
                break;

            case FrameType.ServerHello:
                SubscribeToDefaultArea();
                if (OnConnected != null)
                {
                    Thread connected = new Thread(() => OnConnected());
                    connected.Start();
                }
                break;

            case FrameType.ServerPing:
                var msgServerPing = new ServerPingMessage(frame.MessageBuffer);
                var now           = TimeSpan.FromTicks(DateTime.UtcNow.Ticks);
                var cmdClientPong = new ClientPongMessage()
                {
                    ServerRequestTimestamp = msgServerPing.ServerTimestamp, ClientRequestTimestamp = now, ClientResponseTimestamp = now
                };
                ReliableMessaging.OnSendFrame(new UdpTransferFrame(FrameType.ClientPong, cmdClientPong.Serialize()));
                break;

            case FrameType.Message:
                LastMessageReceived = DateTime.Now;
                ReliableMessaging.ProcessMessageFrame(frame);
                break;

            default:
                throw new NotImplementedException(frame.Type.ToString());
            }
        }
        /// <summary>Subscribes to default area.</summary>
        private void SubscribeToDefaultArea()
        {
            ulong areaId = Locator.GetAreaIdFromWorldPosition(location);

            ReliableMessaging.SendCommand(0, new SubscribeAreaCommand(ClientId, areaId, 0), 0);
        }