/// <summary>
        ///     Initialize a new MatchmakingRequest object
        /// </summary>
        /// <param name="client">
        ///     An already existing MatchmakingClient to use as the client for the request
        /// </param>
        /// <param name="request">
        ///     The ticket data to send with the matchmaking request.
        ///     Data will be copied internally on construction and treated as immutable.
        /// </param>
        /// <param name="timeoutMs">
        ///     The amount of time to wait (in ms) before aborting an incomplete MatchmakingRequest after it has been sent.
        ///     Match requests that time out on the client side will immediately be set to completed and stop listening for a match
        ///     assignment.
        /// </param>
        public MatchmakingRequest(MatchmakingClient client, CreateTicketRequest request, uint timeoutMs = 0)
        {
            m_Client = client
                       ?? throw new ArgumentNullException(nameof(client), logPre + $"Matchmaking {nameof(client)} must not be null");

            if (request == null)
            {
                throw new ArgumentNullException(nameof(request), logPre + $"{nameof(request)} must be a non-null, valid {nameof(CreateTicketRequest)} object");
            }

            // Try to immediately create and store the protobuf version of the CreateTicketRequest
            //  This allows us to fail fast, and also copies the data to prevent it from being mutable
            //  This may cause exceptions inside the protobuf code, which is fine since we're in the constructor
            var createTicketRequest = new Protobuf.CreateTicketRequest();


            string key = nameof(QosTicketInfo).ToLower();

            if (request.Properties != null && !request.Properties.ContainsKey(key))
            {
                QosTicketInfo results = QosConnector.Instance.Execute();
                if (results?.QosResults?.Count > 0)
                {
                    request.Properties = request.Properties ?? new Dictionary <string, string>();
                    request.Properties.Add(key, JsonUtility.ToJson(results));
                }
            }

            // Only set properties if not null
            // Request properties have to be massaged to be protobuf ByteString compatible
            if (request.Properties != null)
            {
                foreach (var kvp in request.Properties)
                {
                    var keyToLower = kvp.Key.ToLower();

#if UNITY_EDITOR || DEVELOPMENT_BUILD
                    if (!kvp.Key.Equals(keyToLower))
                    {
                        Debug.LogWarning(logPre + $"Ticket property with key {kvp.Key} must be all lowercase; changing in-place.");
                    }
#endif
                    createTicketRequest.Properties.Add(keyToLower, ByteString.CopyFrom(Encoding.UTF8.GetBytes(kvp.Value)));
                }
            }

            // Only add attributes if they exist
            if (request?.Attributes?.Count > 0)
            {
                createTicketRequest.Attributes.Add(request.Attributes);
            }

            m_CreateTicketRequest = createTicketRequest;

            State = MatchmakingRequestState.NotStarted;

            m_MatchRequestTimeoutMs = timeoutMs;
        }
Exemple #2
0
 /// <summary>
 ///     <para>Send a Create Ticket (POST) request to the matchmaker, including custom request data.</para>
 ///     <para>On completion, response body will contain a unique Ticket ID, used for GET and DELETE calls</para>
 /// </summary>
 /// <param name="request">The request data to include with the request</param>
 /// <param name="timeout">The timeout for the underlying web request</param>
 /// <returns>
 ///     A UnityWebRequestAsyncOperation containing the underlying UnityWebRequest; can be yielded or used to track
 ///     completion of the request
 /// </returns>
 public UnityWebRequestAsyncOperation CreateTicketAsync(Protobuf.CreateTicketRequest request, int timeout = 0)
 {
     return(CreateTicketAsync(MatchmakingServiceUrl, request, timeout));
 }
Exemple #3
0
        /// <summary>
        ///     <para>Send a Create Ticket (POST) request to the matchmaker, including custom request data.</para>
        ///     <para>On completion, response body will contain a unique Ticket ID, used for GET and DELETE calls</para>
        /// </summary>
        /// <param name="matchmakingServiceUrl">The matchmaker to send the request to</param>
        /// <param name="request">The request data to include with the request</param>
        /// <param name="timeout">The timeout for the underlying web request</param>
        /// <returns>
        ///     A UnityWebRequestAsyncOperation containing the underlying UnityWebRequest; can be yielded or used to track
        ///     completion of the request
        /// </returns>
        public static UnityWebRequestAsyncOperation CreateTicketAsync(string matchmakingServiceUrl, Protobuf.CreateTicketRequest request, int timeout = 0)
        {
            if (string.IsNullOrEmpty(matchmakingServiceUrl))
            {
                throw new ArgumentException(k_LogPre + $"{nameof(matchmakingServiceUrl)} must be a non-null, non-0-length string", nameof(matchmakingServiceUrl));
            }

            if (request == null)
            {
                throw new ArgumentNullException(nameof(request), k_LogPre + $"{nameof(request)} must not be null");
            }

            var url        = matchmakingServiceUrl + k_TicketsPath;
            var webRequest = new UnityWebRequest(url, "POST");

            webRequest.SetRequestHeader("Accept", k_ContentTypeProtobuf);
            webRequest.SetRequestHeader("Content-Type", k_ContentTypeProtobuf);
            webRequest.downloadHandler = new DownloadHandlerBuffer();
            webRequest.timeout         = timeout > 0 ? timeout : k_DefaultCreateCallTimeoutSeconds;

            // Upload body data if it exists (if sending no attributes and no properties, this may be empty)
            var requestBody = request.ToByteArray();

            if (requestBody.Length > 0)
            {
                webRequest.uploadHandler = new UploadHandlerRaw(requestBody);
            }

            return(webRequest.SendWebRequest());
        }