initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 45192af4b21e64233bf08a0caa2fa7ce
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,30 @@
using System;
namespace Unity.Services.Core.Analytics
{
/// <summary>
/// Extensions of InitializationOptions for Analytics
/// </summary>
public static class AnalyticsOptionsExtensions
{
internal const string AnalyticsUserIdKey = "com.unity.services.core.analytics-user-id";
/// <summary>
/// Stores the user id for Analytics.
/// </summary>
/// <param name="self">The InitializationOptions object to modify</param>
/// <param name="id">The custom user id for Analytics.</param>
/// <exception cref="ArgumentException">Throws a <see cref="ArgumentException"/> if id is null or empty.</exception>
/// <returns>
/// Return <paramref name="self"/>.
/// Fluent interface pattern to make it easier to chain set options operations.
/// </returns>
[Obsolete("SetAnalyticsUserId is deprecated. Please use UnityServices.ExternalUserId instead.", false)]
public static InitializationOptions SetAnalyticsUserId(this InitializationOptions self, string id)
{
if (string.IsNullOrEmpty(id))
throw new ArgumentException("Analytics user id cannot be null or empty.", nameof(id));
return self.SetOption(AnalyticsUserIdKey, id);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 73a7759b168f2422f976ca481279904f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
using System.Runtime.CompilerServices;
#if UNITY_INCLUDE_TESTS
[assembly: InternalsVisibleTo("Unity.Services.Core.Tests")]
[assembly: InternalsVisibleTo("Unity.Services.Core.EditorTests")]
[assembly: InternalsVisibleTo("Unity.Services.Core.TestUtils.Tests")]
[assembly: InternalsVisibleTo("Unity.Services.Core.TestUtils.EditorTests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9b1c3b381f42945578ff44373134d0cc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,10 @@
// This file is generated. Do not modify by hand.
// XML documentation file not found. To check if public methods have XML comments,
// make sure the XML doc file is present and located next to the scraped dll
namespace Unity.Services.Core.Analytics
{
public static class AnalyticsOptionsExtensions
{
[System.Obsolete(@"SetAnalyticsUserId is deprecated. Please use UnityServices.ExternalUserId instead.", false)] public static InitializationOptions SetAnalyticsUserId(this InitializationOptions self, string id);
}
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3acc39c28cb7b4e14aec130471988144
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,15 @@
{
"name": "Unity.Services.Core.Analytics",
"references": [
"Unity.Services.Core"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1104de264d522446f8274872ebf70b3d
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6dd1d833aa21340a0b572f70c1d0ea22
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,14 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Unity.Services.Core.Registration")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Configuration.Editor")]
[assembly: InternalsVisibleTo("Unity.Services.Core.TestUtils")]
// Test assemblies
#if UNITY_INCLUDE_TESTS
[assembly: InternalsVisibleTo("Unity.Services.Core.EditorTests")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Tests")]
[assembly: InternalsVisibleTo("Unity.Services.Core.TestUtils.Tests")]
[assembly: InternalsVisibleTo("Unity.Services.Core.TestUtils.EditorTests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 784151075867944a995c363a19d75790
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,13 @@
using UnityEngine;
using Unity.Services.Core.Configuration.Internal;
namespace Unity.Services.Core.Configuration
{
class CloudProjectId : ICloudProjectId
{
public string GetCloudProjectId()
{
return Application.cloudProjectId;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac89e17024bc24b4dbbc6c7d233b333f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Unity.Services.Core.Internal;
using UnityEngine;
namespace Unity.Services.Core.Configuration
{
static class ConfigurationCollectionHelper
{
public static void FillWith(
this IDictionary<string, ConfigurationEntry> self, SerializableProjectConfiguration config)
{
for (var i = 0; i < config.Keys.Length; i++)
{
var entryKey = config.Keys[i];
var entryValue = config.Values[i];
self.SetOrCreateEntry(entryKey, entryValue);
}
}
public static void FillWith(
this IDictionary<string, ConfigurationEntry> self, InitializationOptions options)
{
foreach (var option in options.Values)
{
var optionValue = Convert.ToString(option.Value, CultureInfo.InvariantCulture);
self.SetOrCreateEntry(option.Key, optionValue);
}
}
static void SetOrCreateEntry(
this IDictionary<string, ConfigurationEntry> self, string key, ConfigurationEntry entry)
{
if (self.TryGetValue(key, out var existingEntry))
{
if (!existingEntry.TrySetValue(entry))
{
CoreLogger.LogWarning(
$"You are attempting to initialize Operate Solution SDK with an option \"{key}\"" +
" which is readonly at runtime and can be modified only through Project Settings." +
" The value provided as initialization option will be ignored." +
$" Please update {nameof(InitializationOptions)} in order to remove this warning.");
}
}
else
{
self[key] = entry;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8403e32bfcb112444bcc3a7f9ea043d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,86 @@
using System;
using Newtonsoft.Json;
using UnityEngine;
namespace Unity.Services.Core.Configuration
{
/// <summary>
/// Wrapper for project configuration values.
/// </summary>
[Serializable]
class ConfigurationEntry
{
[JsonRequired]
[SerializeField]
string m_Value;
/// <summary>
/// Get the stored configuration value.
/// </summary>
[JsonIgnore]
public string Value => m_Value;
[JsonRequired]
[SerializeField]
bool m_IsReadOnly;
/// <summary>
/// If true, <see cref="Value"/> can't be changed.
/// </summary>
[JsonIgnore]
public bool IsReadOnly
{
get => m_IsReadOnly;
internal set => m_IsReadOnly = value;
}
/// <summary>
/// Create a new instance of the <see cref="ConfigurationEntry"/> class.
/// </summary>
/// <remarks>
/// Required for serialization.
/// </remarks>
public ConfigurationEntry() {}
/// <summary>
/// Create a new instance of the <see cref="ConfigurationEntry"/> class.
/// </summary>
/// <param name="value">
/// The value to store.
/// </param>
/// <param name="isReadOnly">
/// If true, the value can't be changed after construction.
/// </param>
public ConfigurationEntry(string value, bool isReadOnly = false)
{
m_Value = value;
m_IsReadOnly = isReadOnly;
}
/// <summary>
/// Set <see cref="Value"/> only if <see cref="IsReadOnly"/> is false.
/// Does nothing otherwise.
/// </summary>
/// <param name="value">
/// The new value to store.
/// </param>
/// <returns>
/// Return true if <see cref="IsReadOnly"/> is false;
/// return false otherwise.
/// </returns>
public bool TrySetValue(string value)
{
if (IsReadOnly)
{
return false;
}
m_Value = value;
return true;
}
public static implicit operator string(ConfigurationEntry entry) => entry.Value;
public static implicit operator ConfigurationEntry(string value) => new ConfigurationEntry(value);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de9e8083c7ded62419890100100933a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,10 @@
namespace Unity.Services.Core.Configuration
{
static class ConfigurationUtils
{
public const string ConfigFileName = "UnityServicesProjectConfiguration.json";
public static IConfigurationLoader ConfigurationLoader { get; internal set; }
= new StreamingAssetsConfigurationLoader();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 249a2fdb5bd0534428138ffd827b1db5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,16 @@
using System;
using Unity.Services.Core.Configuration.Internal;
namespace Unity.Services.Core.Configuration
{
class ExternalUserId : IExternalUserId
{
public string UserId => UnityServices.ExternalUserIdProperty.UserId;
public event Action<string> UserIdChanged
{
add => UnityServices.ExternalUserIdProperty.UserIdChanged += value;
remove => UnityServices.ExternalUserIdProperty.UserIdChanged -= value;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c23475166c0634642a1feebc28f06c4d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Unity.Services.Core.Configuration
{
interface IConfigurationLoader
{
Task<SerializableProjectConfiguration> GetConfigAsync();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 329750b2a7303a4469bcbd1fa0b517a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,16 @@
using System.Threading.Tasks;
namespace Unity.Services.Core.Configuration
{
class MemoryConfigurationLoader : IConfigurationLoader
{
public SerializableProjectConfiguration Config { get; set; }
Task<SerializableProjectConfiguration> IConfigurationLoader.GetConfigAsync()
{
var completionSource = new TaskCompletionSource<SerializableProjectConfiguration>();
completionSource.SetResult(Config);
return completionSource.Task;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 63b177b347759a44592a524a22a1b36f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,72 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Newtonsoft.Json;
using Unity.Services.Core.Configuration.Internal;
namespace Unity.Services.Core.Configuration
{
class ProjectConfiguration : IProjectConfiguration
{
string m_JsonCache;
readonly IReadOnlyDictionary<string, ConfigurationEntry> m_ConfigValues;
public ProjectConfiguration(IReadOnlyDictionary<string, ConfigurationEntry> configValues)
{
m_ConfigValues = configValues;
}
public bool GetBool(string key, bool defaultValue = default)
{
var stringConfig = GetString(key);
if (bool.TryParse(stringConfig, out var parsedValue))
{
return parsedValue;
}
return defaultValue;
}
public int GetInt(string key, int defaultValue = default)
{
var stringConfig = GetString(key);
if (int.TryParse(stringConfig, out var parsedValue))
{
return parsedValue;
}
return defaultValue;
}
public float GetFloat(string key, float defaultValue = default)
{
var stringConfig = GetString(key);
if (float.TryParse(stringConfig, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsedValue))
{
return parsedValue;
}
return defaultValue;
}
public string GetString(string key, string defaultValue = default)
{
if (m_ConfigValues.TryGetValue(key, out var configValue))
{
return configValue.Value;
}
return defaultValue;
}
public string ToJson()
{
if (m_JsonCache == null)
{
var dict = m_ConfigValues.ToDictionary(pair => pair.Key, pair => pair.Value.Value);
m_JsonCache = JsonConvert.SerializeObject(dict);
}
return m_JsonCache;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2458d7ed2cd22964bb2de41ded78bca8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
namespace Unity.Services.Core.Configuration
{
[Serializable]
struct SerializableProjectConfiguration
{
public static SerializableProjectConfiguration Empty
=> new SerializableProjectConfiguration
{
Keys = Array.Empty<string>(),
Values = Array.Empty<ConfigurationEntry>(),
};
[JsonRequired]
[SerializeField]
internal string[] Keys;
[JsonRequired]
[SerializeField]
internal ConfigurationEntry[] Values;
public SerializableProjectConfiguration(IDictionary<string, ConfigurationEntry> configValues)
{
Keys = new string[configValues.Count];
Values = new ConfigurationEntry[configValues.Count];
var i = 0;
foreach (var configValue in configValues)
{
Keys[i] = configValue.Key;
Values[i] = configValue.Value;
++i;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 17c935ca4d9d95048931d5aec5d99d97
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,16 @@
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Unity.Services.Core.Configuration
{
class StreamingAssetsConfigurationLoader : IConfigurationLoader
{
public async Task<SerializableProjectConfiguration> GetConfigAsync()
{
var jsonConfig = await StreamingAssetsUtils.GetFileTextFromStreamingAssetsAsync(
ConfigurationUtils.ConfigFileName);
var config = JsonConvert.DeserializeObject<SerializableProjectConfiguration>(jsonConfig);
return config;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5d7186a4ae434942afddf441cccaa67
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
// This file is generated. Do not modify by hand.
// XML documentation file not found. To check if public methods have XML comments,
// make sure the XML doc file is present and located next to the scraped dll

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3fdb983cd9c6943db94f76b0e6462317
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,16 @@
{
"name": "Unity.Services.Core.Configuration",
"references": [
"Unity.Services.Core.Internal",
"Unity.Services.Core"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4077802dea91b4b6d878b48b4160bd81
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: abf176c60f5545c4e84eeca86e38a31a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,38 @@
#if !UNITY_EDITOR && (UNITY_ANDROID || UNITY_WEBGL)
#define READ_STREMAING_ASSETS_WITH_WEB_REQUEST
#endif
using System;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
#if READ_STREMAING_ASSETS_WITH_WEB_REQUEST
using Unity.Services.Core.Internal;
#endif
namespace Unity.Services.Core.Configuration
{
static class StreamingAssetsUtils
{
public static Task<string> GetFileTextFromStreamingAssetsAsync(string path)
{
var fullPath = Path.Combine(Application.streamingAssetsPath, path);
#if READ_STREMAING_ASSETS_WITH_WEB_REQUEST
return UnityWebRequestUtils.GetTextAsync(fullPath);
#else
var completionSource = new TaskCompletionSource<string>();
try
{
var fileText = File.ReadAllText(fullPath);
completionSource.SetResult(fileText);
}
catch (Exception e)
{
completionSource.SetException(e);
}
return completionSource.Task;
#endif
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3fefd9c9a0e33734aba3b2fc03b44585
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 82f8d759ea41b46549f0c3a2d4165ec6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,32 @@
using System.Runtime.CompilerServices;
// Access to AsyncOperation (deprecated)
[assembly: InternalsVisibleTo("Unity.Services.Authentication")]
[assembly: InternalsVisibleTo("Unity.Services.Authentication.Editor")]
#if UNITY_INCLUDE_TESTS
[assembly: InternalsVisibleTo("Unity.Services.Authentication.Tests")]
[assembly: InternalsVisibleTo("Unity.Services.Authentication.EditorTests")]
#endif
[assembly: InternalsVisibleTo("Unity.Services.Core.TestUtils")]
// Required for access to Networking API
[assembly: InternalsVisibleTo("Unity.Services.Core.Editor")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Networking")]
// Required for CoreLogger access
[assembly: InternalsVisibleTo("Unity.Services.Core.Configuration")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Configuration.Editor")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Registration")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Scheduler")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Telemetry")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Threading")]
// Test assemblies
#if UNITY_INCLUDE_TESTS
[assembly: InternalsVisibleTo("Unity.Services.Core.Tests")]
[assembly: InternalsVisibleTo("Unity.Services.Core.EditorTests")]
[assembly: InternalsVisibleTo("Unity.Services.Core.TestUtils.Tests")]
[assembly: InternalsVisibleTo("Unity.Services.Core.TestUtils.EditorTests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
#endif

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a7624b141c8742c78133946b1e5643d7
timeCreated: 1622749740

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 24217193ca52348f793854bafd71c78f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,223 @@
using System;
using System.Collections;
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Default implementation for <see cref="IAsyncOperation"/>.
/// </summary>
class AsyncOperation : IAsyncOperation
{
/// <inheritdoc/>
public bool IsDone { get; protected set; }
/// <inheritdoc/>
public AsyncOperationStatus Status { get; protected set; }
/// <inheritdoc/>
public event Action<IAsyncOperation> Completed
{
add
{
if (IsDone)
value(this);
else
m_CompletedCallback += value;
}
remove => m_CompletedCallback -= value;
}
/// <inheritdoc/>
public Exception Exception { get; protected set; }
/// <inheritdoc cref="IAsyncOperation.Completed"/>
protected Action<IAsyncOperation> m_CompletedCallback;
/// <summary>
/// Set this operation's status <see cref="AsyncOperationStatus.InProgress"/>.
/// </summary>
public void SetInProgress()
{
Status = AsyncOperationStatus.InProgress;
}
/// <summary>
/// Complete this operation as a success.
/// </summary>
public void Succeed()
{
if (IsDone)
{
return;
}
IsDone = true;
Status = AsyncOperationStatus.Succeeded;
m_CompletedCallback?.Invoke(this);
m_CompletedCallback = null;
}
/// <summary>
/// Complete this operation as a failure using the given <paramref name="reason"/>.
/// </summary>
/// <param name="reason">
/// The exception at the source of the failure.
/// </param>
public void Fail(Exception reason)
{
if (IsDone)
{
return;
}
Exception = reason;
IsDone = true;
Status = AsyncOperationStatus.Failed;
m_CompletedCallback?.Invoke(this);
m_CompletedCallback = null;
}
/// <summary>
/// Complete this operation as a cancellation.
/// </summary>
public void Cancel()
{
if (IsDone)
{
return;
}
Exception = new OperationCanceledException();
IsDone = true;
Status = AsyncOperationStatus.Cancelled;
m_CompletedCallback?.Invoke(this);
m_CompletedCallback = null;
}
/// <inheritdoc/>
bool IEnumerator.MoveNext() => !IsDone;
/// <inheritdoc/>
/// <remarks>
/// Left empty because we don't support operation reset.
/// </remarks>
void IEnumerator.Reset() {}
/// <inheritdoc/>
object IEnumerator.Current => null;
}
/// <summary>
/// Default implementation for <see cref="IAsyncOperation{T}"/>.
/// </summary>
/// <typeparam name="T">
/// The result's type of this operation.
/// </typeparam>
class AsyncOperation<T> : IAsyncOperation<T>
{
/// <inheritdoc/>
public bool IsDone { get; protected set; }
/// <inheritdoc/>
public AsyncOperationStatus Status { get; protected set; }
/// <inheritdoc/>
public event Action<IAsyncOperation<T>> Completed
{
add
{
if (IsDone)
value(this);
else
m_CompletedCallback += value;
}
remove => m_CompletedCallback -= value;
}
/// <inheritdoc/>
public Exception Exception { get; protected set; }
/// <inheritdoc/>
public T Result { get; protected set; }
/// <inheritdoc cref="IAsyncOperation{T}.Completed"/>
protected Action<IAsyncOperation<T>> m_CompletedCallback;
/// <summary>
/// Set this operation's status <see cref="AsyncOperationStatus.InProgress"/>.
/// </summary>
public void SetInProgress()
{
Status = AsyncOperationStatus.InProgress;
}
/// <summary>
/// Complete this operation as a success and set its result.
/// </summary>
/// <param name="result">
/// The result of this operation.
/// </param>
public void Succeed(T result)
{
if (IsDone)
{
return;
}
Result = result;
IsDone = true;
Status = AsyncOperationStatus.Succeeded;
m_CompletedCallback?.Invoke(this);
m_CompletedCallback = null;
}
/// <summary>
/// Complete this operation as a failure using the given <paramref name="reason"/>.
/// </summary>
/// <param name="reason">
/// The exception at the source of the failure.
/// </param>
public void Fail(Exception reason)
{
if (IsDone)
{
return;
}
Exception = reason;
IsDone = true;
Status = AsyncOperationStatus.Failed;
m_CompletedCallback?.Invoke(this);
m_CompletedCallback = null;
}
/// <summary>
/// Complete this operation as a cancellation.
/// </summary>
public void Cancel()
{
if (IsDone)
{
return;
}
Exception = new OperationCanceledException();
IsDone = true;
Status = AsyncOperationStatus.Cancelled;
m_CompletedCallback?.Invoke(this);
m_CompletedCallback = null;
}
/// <inheritdoc/>
bool IEnumerator.MoveNext() => !IsDone;
/// <inheritdoc/>
/// <remarks>
/// Left empty because we don't support operation reset.
/// </remarks>
void IEnumerator.Reset() {}
/// <inheritdoc/>
object IEnumerator.Current => null;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1978478d5dedf4c0bbc8a8ac97566699
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,105 @@
using System;
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Default implementation for <see cref="IAsyncOperationAwaiter"/>.
/// </summary>
struct AsyncOperationAwaiter : IAsyncOperationAwaiter
{
IAsyncOperation m_Operation;
/// <summary>
/// Create an awaiter for the given <paramref name="asyncOperation"/>.
/// </summary>
/// <param name="asyncOperation">
/// The operation to await.
/// </param>
public AsyncOperationAwaiter(IAsyncOperation asyncOperation)
{
m_Operation = asyncOperation;
}
/// <summary>
/// Schedules the continuation action that's invoked when the instance completes.
/// </summary>
/// <param name="continuation">
/// The action to invoke when the operation completes.
/// </param>
/// <remarks>
/// Straightforward implementation of <see cref="System.Runtime.CompilerServices.ICriticalNotifyCompletion"/>.
/// </remarks>
public void OnCompleted(Action continuation)
{
m_Operation.Completed += operation => continuation();
}
/// <inheritdoc cref="OnCompleted"/>
public void UnsafeOnCompleted(Action continuation)
{
m_Operation.Completed += operation => continuation();
}
/// <inheritdoc/>
public bool IsCompleted => m_Operation.IsDone;
/// <inheritdoc/>
public void GetResult()
{
if (m_Operation.Status == AsyncOperationStatus.Failed
|| m_Operation.Status == AsyncOperationStatus.Cancelled)
{
throw m_Operation.Exception;
}
}
}
/// <summary>
/// Default implementation for <see cref="IAsyncOperationAwaiter{T}"/>.
/// </summary>
/// <typeparam name="T">
/// The result's type of the awaited operation.
/// </typeparam>
struct AsyncOperationAwaiter<T> : IAsyncOperationAwaiter<T>
{
IAsyncOperation<T> m_Operation;
/// <summary>
/// Create an awaiter for the given <paramref name="asyncOperation"/>.
/// </summary>
/// <param name="asyncOperation">
/// The operation to await.
/// </param>
public AsyncOperationAwaiter(IAsyncOperation<T> asyncOperation)
{
m_Operation = asyncOperation;
}
/// <inheritdoc cref="AsyncOperationAwaiter.OnCompleted"/>
public void OnCompleted(Action continuation)
{
m_Operation.Completed += obj => continuation();
}
/// <inheritdoc cref="AsyncOperationAwaiter.UnsafeOnCompleted"/>
public void UnsafeOnCompleted(Action continuation)
{
m_Operation.Completed += obj => continuation();
}
/// <inheritdoc/>
public bool IsCompleted => m_Operation.IsDone;
/// <inheritdoc/>
public T GetResult()
{
if (m_Operation.Status == AsyncOperationStatus.Failed
|| m_Operation.Status == AsyncOperationStatus.Cancelled)
{
throw m_Operation.Exception;
}
return m_Operation.Result;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3755af4fd119427481c46ab5946719c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,206 @@
using System;
using System.Runtime.CompilerServices;
using UnityEngine;
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Base class for asynchronous operations.
///
/// Implemented by: TaskAsyncOperation
/// </summary>
abstract class AsyncOperationBase : CustomYieldInstruction, IAsyncOperation, INotifyCompletion
{
/// <summary>
/// Indicates if coroutine should be kept suspended.
///
/// From CustomYieldInstruction.
/// </summary>
public override bool keepWaiting => !IsCompleted;
/// <summary>
/// Whether this operation is completed.
///
/// Required to make the operation awaitable
/// </summary>
public abstract bool IsCompleted { get; }
/// <summary>
/// If true, this operation either succeeded, failed, or has been canceled.
///
/// From IAsyncOperation
/// </summary>
public bool IsDone => IsCompleted;
/// <summary>
/// The current status of this operation.
///
/// From IAsyncOperation
/// </summary>
public abstract AsyncOperationStatus Status { get; }
/// <summary>
/// The exception that occured during the operation if it failed.
///
/// From IAsyncOperation
/// </summary>
public abstract Exception Exception { get; }
/// <summary>
/// Result of the operation.
///
/// Required to make the operation awaitable
/// </summary>
public abstract void GetResult();
/// <summary>
/// Awaiter on the operation.
///
/// Required to make the operation awaitable
/// </summary>
public abstract AsyncOperationBase GetAwaiter();
Action<IAsyncOperation> m_CompletedCallback;
/// <summary>
/// Event raised when the operation succeeded or failed.
/// The argument is the operation that raised the event.
///
/// From IAsyncOperation
/// </summary>
public event Action<IAsyncOperation> Completed
{
add
{
if (IsDone)
{
value(this);
}
else
{
m_CompletedCallback += value;
}
}
remove => m_CompletedCallback -= value;
}
protected void DidComplete()
{
m_CompletedCallback?.Invoke(this);
}
/// <summary>Schedules the continuation action that's invoked when the instance completes.</summary>
/// <param name="continuation">The action to invoke when the operation completes.</param>
///
/// From INotifyCompletion
public virtual void OnCompleted(Action continuation)
{
Completed += op => continuation?.Invoke();
}
}
/// <summary>
/// Base class for asynchronous operations.
///
/// Implemented by: TaskAsyncOperation<T>
/// </summary>
/// <typeparam name="T">
/// The type of this operation's result
/// </typeparam>
abstract class AsyncOperationBase<T> : CustomYieldInstruction, IAsyncOperation<T>, INotifyCompletion
{
/// <summary>
/// Indicates if coroutine should be kept suspended.
///
/// From CustomYieldInstruction.
/// </summary>
public override bool keepWaiting => !IsCompleted;
/// <summary>
/// Whether this operation is completed.
///
/// Required to make the operation awaitable
/// </summary>
public abstract bool IsCompleted { get; }
/// <summary>
/// If true, this operation either succeeded, failed, or has been canceled.
///
/// From IAsyncOperation
/// </summary>
public bool IsDone => IsCompleted;
/// <summary>
/// The current status of this operation.
///
/// From IAsyncOperation
/// </summary>
public abstract AsyncOperationStatus Status { get; }
/// <summary>
/// The exception that occured during the operation if it failed.
///
/// From IAsyncOperation
/// </summary>
public abstract Exception Exception { get; }
/// <summary>
/// Result of the operation.
///
/// Required to make the operation awaitable
/// </summary>
public abstract T Result { get; }
/// <summary>
/// Awaiter on the operation.
///
/// Required to make the operation awaitable
/// </summary>
public abstract T GetResult();
/// <summary>
/// Awaiter on the operation.
///
/// Required to make the operation awaitable
/// </summary>
public abstract AsyncOperationBase<T> GetAwaiter();
Action<IAsyncOperation<T>> m_CompletedCallback;
/// <summary>
/// Event raised when the operation succeeded or failed.
/// The argument is the operation that raised the event.
///
/// From IAsyncOperation
/// </summary>
public event Action<IAsyncOperation<T>> Completed
{
add
{
if (IsDone)
{
value(this);
}
else
{
m_CompletedCallback += value;
}
}
remove => m_CompletedCallback -= value;
}
protected void DidComplete()
{
m_CompletedCallback?.Invoke(this);
}
/// <summary>Schedules the continuation action that's invoked when the instance completes.</summary>
/// <param name="continuation">The action to invoke when the operation completes.</param>
///
/// From INotifyCompletion
public virtual void OnCompleted(Action continuation)
{
Completed += op => continuation?.Invoke();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: db331124c2ee348219007881f953471b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,147 @@
using System;
using System.Threading.Tasks;
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Set of utility functions added as extensions to
/// <see cref="IAsyncOperation"/> and <see cref="IAsyncOperation{T}"/>.
/// </summary>
static class AsyncOperationExtensions
{
/// <summary>
/// Get a default awaiter on <paramref name="self"/>.
/// </summary>
/// <param name="self">
/// The operation to create an awaiter for.
/// </param>
/// <returns>
/// Return a default awaiter for <paramref name="self"/>.
/// </returns>
/// <remarks>
/// This is required so we can directly use the <see langword="await"/>
/// keyword on an <see cref="IAsyncOperation"/>.
/// </remarks>
public static AsyncOperationAwaiter GetAwaiter(this IAsyncOperation self)
{
return new AsyncOperationAwaiter(self);
}
/// <summary>
/// Get a Task based on <paramref name="self"/>.
/// </summary>
/// <param name="self">
/// The operation to create a Task for.
/// </param>
/// <returns>
/// Return a <see cref="T:System.Threading.Tasks.Task"/>.
/// </returns>
public static Task AsTask(this IAsyncOperation self)
{
if (self.Status == AsyncOperationStatus.Succeeded)
{
return Task.CompletedTask;
}
var taskCompletionSource = new TaskCompletionSource<object>();
void CompleteTask(IAsyncOperation operation)
{
switch (operation.Status)
{
case AsyncOperationStatus.Failed:
taskCompletionSource.TrySetException(operation.Exception);
break;
case AsyncOperationStatus.Cancelled:
taskCompletionSource.TrySetCanceled();
break;
case AsyncOperationStatus.Succeeded:
taskCompletionSource.TrySetResult(null);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
if (self.IsDone)
{
CompleteTask(self);
}
else
{
self.Completed += CompleteTask;
}
return taskCompletionSource.Task;
}
/// <summary>
/// Get a default awaiter for <paramref name="self"/>.
/// </summary>
/// <param name="self">
/// The operation to create an awaiter for.
/// </param>
/// <typeparam name="T">
/// The result's type of <paramref name="self"/>.
/// </typeparam>
/// <returns>
/// Return a default awaiter for <paramref name="self"/>.
/// </returns>
/// <remarks>
/// This is required so we can directly use the <see langword="await"/>
/// keyword on an <see cref="IAsyncOperation{T}"/>.
/// </remarks>
public static AsyncOperationAwaiter<T> GetAwaiter<T>(this IAsyncOperation<T> self)
{
return new AsyncOperationAwaiter<T>(self);
}
/// <summary>
/// Get a Task based on <paramref name="self"/>.
/// </summary>
/// <param name="self">
/// The operation to create a Task for.
/// </param>
/// <typeparam name="T">
/// The result's type of <paramref name="self"/>.
/// </typeparam>
/// <returns>
/// Return a <see cref="T:System.Threading.Tasks.Task`1"/>
/// </returns>
public static Task<T> AsTask<T>(this IAsyncOperation<T> self)
{
var taskCompletionSource = new TaskCompletionSource<T>();
void CompleteTask(IAsyncOperation<T> operation)
{
switch (operation.Status)
{
case AsyncOperationStatus.Succeeded:
taskCompletionSource.TrySetResult(operation.Result);
break;
case AsyncOperationStatus.Failed:
taskCompletionSource.TrySetException(operation.Exception);
break;
case AsyncOperationStatus.Cancelled:
taskCompletionSource.TrySetCanceled();
break;
default:
throw new ArgumentOutOfRangeException();
}
}
if (self.IsDone)
{
CompleteTask(self);
}
else
{
self.Completed += CompleteTask;
}
return taskCompletionSource.Task;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bd3488b91e5f84fb18390042c3ebc70b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,29 @@
namespace Unity.Services.Core.Internal
{
/// <summary>
/// All supported status of an <see cref="IAsyncOperation"/>.
/// </summary>
enum AsyncOperationStatus
{
/// <summary>
/// The operation status hasn't been defined yet.
/// </summary>
None,
/// <summary>
/// The operation is running.
/// </summary>
InProgress,
/// <summary>
/// The operation is completed without any errors.
/// </summary>
Succeeded,
/// <summary>
/// The operation is completed with errors.
/// </summary>
Failed,
/// <summary>
/// The operation has been canceled.
/// </summary>
Cancelled
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d4f47b43625b43508b700e345be22c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,61 @@
using System;
using System.Collections;
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Contract for an asynchronous operation with no result.
/// </summary>
interface IAsyncOperation : IEnumerator
{
/// <summary>
/// If true, this operation either succeeded, failed, or has been canceled.
/// </summary>
bool IsDone { get; }
/// <summary>
/// The current status of this operation.
/// </summary>
AsyncOperationStatus Status { get; }
/// <summary>
/// Event raised when the operation succeeded or failed.
/// The argument is the operation that raised the event.
/// </summary>
event Action<IAsyncOperation> Completed;
/// <summary>
/// The exception that occured during the operation if it failed.
/// </summary>
Exception Exception { get; }
}
/// <summary>
/// Contract for an asynchronous operation returning a result.
/// </summary>
/// <typeparam name="T">
/// The result's type of this operation.
/// </typeparam>
interface IAsyncOperation<out T> : IEnumerator
{
/// <inheritdoc cref="IAsyncOperation.IsDone"/>
bool IsDone { get; }
/// <inheritdoc cref="IAsyncOperation.Status"/>
AsyncOperationStatus Status { get; }
/// <summary>
/// Event raised when the operation succeeded or failed.
/// The argument is the operation that raised the event.
/// </summary>
event Action<IAsyncOperation<T>> Completed;
/// <inheritdoc cref="IAsyncOperation.Exception"/>
Exception Exception { get; }
/// <summary>
/// The result of this operation.
/// </summary>
T Result { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fac66275348d245d490b160bcf2413c3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,51 @@
using System.Runtime.CompilerServices;
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Contract for objects allowing to use the <see langword="await"/> keyword on an <see cref="IAsyncOperation"/>.
/// </summary>
/// <remarks>
/// For more information, see <see href="https://github.com/dotnet/roslyn/blob/master/docs/features/task-types.md"/>
/// </remarks>
interface IAsyncOperationAwaiter : ICriticalNotifyCompletion
{
/// <inheritdoc cref="IAsyncOperation.IsDone"/>
bool IsCompleted { get; }
/// <summary>
/// Get the operation's current result.
/// </summary>
/// <remarks>
/// * Does nothing on success but must be declared to match the awaiter pattern.
/// * Is expected to throw if the operation failed or has been canceled.
/// </remarks>
void GetResult();
}
/// <summary>
/// Contract for objects allowing to use the <see langword="await"/> keyword on an <see cref="IAsyncOperation{T}"/>.
/// </summary>
/// <typeparam name="T">
/// The result's type of the awaited operation.
/// </typeparam>
/// <remarks>
/// For more information, see <see href="https://github.com/dotnet/roslyn/blob/master/docs/features/task-types.md"/>
/// </remarks>
interface IAsyncOperationAwaiter<out T> : ICriticalNotifyCompletion
{
/// <inheritdoc cref="IAsyncOperation.IsDone"/>
bool IsCompleted { get; }
/// <summary>
/// Get the operation's current result.
/// </summary>
/// <returns>
/// Return the operation's current <see cref="IAsyncOperation{T}.Result"/>.
/// </returns>
/// <remarks>
/// Is expected to throw if the operation failed or has been canceled.
/// </remarks>
T GetResult();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c6da497a894c04c6d9b6a738042ec6a0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,223 @@
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Task-based implementation of IAsyncOperation.
///
/// awaitable in tasks
/// yieldable in coroutines
/// </summary>
class TaskAsyncOperation : AsyncOperationBase, INotifyCompletion
{
/// <remarks>
/// The scheduler is also used by the <see cref="TaskAsyncOperation{T}"/> because
/// <see cref="RuntimeInitializeOnLoadMethodAttribute"/> can't be used in generic objects.
/// </remarks>
internal static TaskScheduler Scheduler;
Task m_Task;
/// <inheritdoc />
public override bool IsCompleted => m_Task.IsCompleted;
/// <inheritdoc />
public override AsyncOperationStatus Status
{
get
{
if (m_Task == null)
{
return AsyncOperationStatus.None;
}
if (!m_Task.IsCompleted)
{
return AsyncOperationStatus.InProgress;
}
if (m_Task.IsCanceled)
{
return AsyncOperationStatus.Cancelled;
}
if (m_Task.IsFaulted)
{
return AsyncOperationStatus.Failed;
}
return AsyncOperationStatus.Succeeded;
}
}
/// <inheritdoc />
public override Exception Exception => m_Task?.Exception;
/// <inheritdoc />
public override void GetResult() {}
/// <inheritdoc />
public override AsyncOperationBase GetAwaiter()
{
return this;
}
/// <summary>
/// Creates a new TaskAsyncOperation from a provided Task.
/// Returns on Unity's main thread context.
/// </summary>
/// <param name="task">
/// The task tracked by this TaskAsyncOperation.
/// </param>
public TaskAsyncOperation(Task task)
{
// Tests don't run `RuntimeInitializeOnLoadMethod`s?
if (Scheduler == null)
{
SetScheduler();
}
m_Task = task;
task.ContinueWith((t, state) =>
{
var self = (TaskAsyncOperation)state;
self.DidComplete();
}, this, CancellationToken.None, TaskContinuationOptions.None, Scheduler);
}
/// <summary>
/// Creates and starts a task from the provided Action executing on the C# thread pool.
/// Returns on Unity's main thread context.
/// </summary>
/// <param name="action">
/// The Action to execute asynchronously.
/// </param>
/// <returns>
/// A TaskAsyncOperation tracking the execution of the provided Action.
/// </returns>
public static TaskAsyncOperation Run(Action action)
{
var task = new Task(action);
var ret = new TaskAsyncOperation(task);
task.Start();
return ret;
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
internal static void SetScheduler()
{
Scheduler = TaskScheduler.FromCurrentSynchronizationContext();
}
}
/// <summary>
/// Task-based implementation of IAsyncOperation<T>.
///
/// awaitable in tasks
/// yieldable in coroutines
/// </summary>
/// <typeparam name="T">
/// The return type of the operation's result.
/// </typeparam>
class TaskAsyncOperation<T> : AsyncOperationBase<T>
{
Task<T> m_Task;
/// <inheritdoc />
public override bool IsCompleted => m_Task.IsCompleted;
/// <inheritdoc />
public override T Result => m_Task.Result;
/// <inheritdoc />
public override T GetResult()
{
return m_Task.GetAwaiter().GetResult();
}
/// <inheritdoc />
public override AsyncOperationBase<T> GetAwaiter()
{
return this;
}
/// <inheritdoc />
public override AsyncOperationStatus Status
{
get
{
if (m_Task == null)
{
return AsyncOperationStatus.None;
}
if (!m_Task.IsCompleted)
{
return AsyncOperationStatus.InProgress;
}
if (m_Task.IsCanceled)
{
return AsyncOperationStatus.Cancelled;
}
if (m_Task.IsFaulted)
{
return AsyncOperationStatus.Failed;
}
return AsyncOperationStatus.Succeeded;
}
}
/// <inheritdoc />
public override Exception Exception => m_Task?.Exception;
/// <summary>
/// Creates a new TaskAsyncOperation from a provided Task.
/// Returns on Unity's main thread context.
/// </summary>
/// <param name="task">
/// The task tracked by this TaskAsyncOperation.
/// </param>
public TaskAsyncOperation(Task<T> task)
{
// Tests don't run `RuntimeInitializeOnLoadMethod`s?
if (TaskAsyncOperation.Scheduler == null)
{
TaskAsyncOperation.SetScheduler();
}
m_Task = task;
task.ContinueWith((t, state) =>
{
var self = (TaskAsyncOperation<T>)state;
self.DidComplete();
}, this, CancellationToken.None, TaskContinuationOptions.None, TaskAsyncOperation.Scheduler);
}
/// <summary>
/// Creates and starts a task from the provided Action executing on the C# thread pool.
/// Returns on Unity's main thread context.
/// </summary>
/// <param name="func">
/// The Action to execute asynchronously.
/// </param>
/// <returns>
/// A TaskAsyncOperation tracking the execution of the provided Action.
/// </returns>
public static TaskAsyncOperation<T> Run(Func<T> func)
{
var task = new Task<T>(func);
var ret = new TaskAsyncOperation<T>(task);
task.Start();
return ret;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7829c22a2e7f648629af71b9abb67494
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 99614a857646842a086184db34d8fb84
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c8f15537a1ce54d2cb26811d0da5627a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,21 @@
using Unity.Services.Core.Internal;
#if UNITY_2020_2_OR_NEWER
using UnityEngine.Scripting;
#endif
namespace Unity.Services.Authentication.Internal
{
/// <summary>
/// Contract for objects providing an access token to access remote services.
/// </summary>
#if UNITY_2020_2_OR_NEWER
[RequireImplementors]
#endif
public interface IAccessToken : IServiceComponent
{
/// <summary>
/// The current token to use to access remote services.
/// </summary>
string AccessToken { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2946cf1ab319d45a9af9d5720e7cc5f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,21 @@
using Unity.Services.Core.Internal;
#if UNITY_2020_2_OR_NEWER
using UnityEngine.Scripting;
#endif
namespace Unity.Services.Authentication.Internal
{
/// <summary>
/// Component providing the Environment Id
/// </summary>
#if UNITY_2020_2_OR_NEWER
[RequireImplementors]
#endif
public interface IEnvironmentId : IServiceComponent
{
/// <summary>
/// Returns the Environment ID when a sign in succeeds, otherwise null.
/// </summary>
string EnvironmentId { get; }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac86a2bfd37d6486e831ba1e932a6f66
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,27 @@
using System;
using Unity.Services.Core.Internal;
#if UNITY_2020_2_OR_NEWER
using UnityEngine.Scripting;
#endif
namespace Unity.Services.Authentication.Internal
{
/// <summary>
/// Contract for objects providing information with the player identification (PlayerID) for currently signed in player.
/// </summary>
#if UNITY_2020_2_OR_NEWER
[RequireImplementors]
#endif
public interface IPlayerId : IServiceComponent
{
/// <summary>
/// The ID of the player.
/// </summary>
string PlayerId { get; }
/// <summary>
/// Event raised when the player id changed.
/// </summary>
event Action<string> PlayerIdChanged;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1c760120bcec444b49d3351b04d063c0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c7fcd0b25211b4456841ec71fd8a103c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,16 @@
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Configuration.Internal
{
/// <summary>
/// Component to provide cloud project ID.
/// </summary>
public interface ICloudProjectId : IServiceComponent
{
/// <summary>
/// Get cloud project ID at runtime.
/// </summary>
/// <returns>cloud project id</returns>
string GetCloudProjectId();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e6a900469855a4439a8cc405993bbe57
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,27 @@
using System;
using Unity.Services.Core.Internal;
#if UNITY_2020_2_OR_NEWER
using UnityEngine.Scripting;
#endif
namespace Unity.Services.Core.Configuration.Internal
{
/// <summary>
/// Component to provide external user ID, provided by a third party provider
/// </summary>
#if UNITY_2020_2_OR_NEWER
[RequireImplementors]
#endif
public interface IExternalUserId : IServiceComponent
{
/// <summary>
/// Get the external user id
/// </summary>
string UserId { get; }
/// <summary>
/// Event raised when the external id changed.
/// </summary>
event Action<string> UserIdChanged;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bd53524449ca040b9910cc0e70379457
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,73 @@
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Configuration.Internal
{
/// <summary>
/// Component for project configuration.
/// </summary>
/// <remarks>
/// For WebGL platform, the configuration is only accessable if the application is hosted behind https. Behind http you will get an error: `Insecure connection not allowed`.
/// </remarks>
public interface IProjectConfiguration : IServiceComponent
{
/// <summary>
/// Get the boolean value for the project config <paramref name="key"/>.
/// </summary>
/// <param name="key">
/// The identifier of the project config to find.
/// </param>
/// <param name="defaultValue">
/// The value returned if there is no match for the given <paramref name="key"/>.
/// </param>
/// <returns>
/// Return the boolean value for the project config for the given <paramref name="key"/> if any;
/// return <paramref name="defaultValue"/> otherwise.
/// </returns>
bool GetBool(string key, bool defaultValue = default);
/// <summary>
/// Get the integer value for the project config with the given <paramref name="key"/>.
/// </summary>
/// <param name="key">
/// The identifier of the project config to find.
/// </param>
/// <param name="defaultValue">
/// The value returned if there is no match for the given <paramref name="key"/>.
/// </param>
/// <returns>
/// Return the integer value for the project config for the given <paramref name="key"/> if any;
/// return <paramref name="defaultValue"/> otherwise.
/// </returns>
int GetInt(string key, int defaultValue = default);
/// <summary>
/// Get the float value for the project config with the given <paramref name="key"/>.
/// </summary>
/// <param name="key">
/// The identifier of the project config to find.
/// </param>
/// <param name="defaultValue">
/// The value returned if there is no match for the given <paramref name="key"/>.
/// </param>
/// <returns>
/// Return the float value for the project config for the given <paramref name="key"/> if any;
/// return <paramref name="defaultValue"/> otherwise.
/// </returns>
float GetFloat(string key, float defaultValue = default);
/// <summary>
/// Get the string value for the project config with the given <paramref name="key"/>.
/// </summary>
/// <param name="key">
/// The identifier of the project config to find.
/// </param>
/// <param name="defaultValue">
/// The value returned if there is no match for the given <paramref name="key"/>.
/// </param>
/// <returns>
/// Return the string value for the project config for the given <paramref name="key"/> if any;
/// return <paramref name="defaultValue"/> otherwise.
/// </returns>
string GetString(string key, string defaultValue = default);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 83e41efdede654a89b901da7b70ff0b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d7e60a737f3cb463e9a120fbe29854e8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,16 @@
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Device.Internal
{
/// <summary>
/// Component providing a Unity Installation Identifier
/// </summary>
public interface IInstallationId : IServiceComponent
{
/// <summary>
/// Returns Unity Installation Identifier
/// </summary>
/// <returns>The Installation Identifier</returns>
string GetOrCreateIdentifier();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2ce7a4ee920834a2eb1b48958047fbd4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: add07ed3db70146bea50b6a4f554e651
timeCreated: 1620137169

View file

@ -0,0 +1,15 @@
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Environments.Internal
{
/// <summary>
/// Component providing the Unity Service Environment
/// </summary>
public interface IEnvironments : IServiceComponent
{
/// <summary>
/// Returns the name of the currently used Unity Service Environment
/// </summary>
string Current { get; }
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9ba8832336df045fca38ac55a6b587f0
timeCreated: 1620137216

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2cbeea08e009b4f1d8f8b2786d63ca25
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,21 @@
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Contract for objects containing all settings to customize the behaviour of a HTTP request sending.
/// </summary>
/// <remarks>
/// More options will be added based on common needs.
/// </remarks>
struct HttpOptions
{
/// <summary>
/// Delay, in seconds, after which the request will be considered a failure.
/// </summary>
public int RequestTimeoutInSeconds;
/// <summary>
/// Indicates the number of redirects the request can follow without failing.
/// </summary>
public int RedirectLimit;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68448537185dd4d6ba109ed748b184f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,206 @@
using System.Collections.Generic;
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Contain all data of an HTTP request.
/// </summary>
class HttpRequest
{
/// <summary>
/// The HTTP method to use.
/// </summary>
/// <example>
/// Common values are: DELETE, GET, PATCH, POST, PUT ...
/// </example>
public string Method;
/// <summary>
/// The targeted url.
/// </summary>
public string Url;
/// <summary>
/// The headers additional information.
/// </summary>
public Dictionary<string, string> Headers;
/// <summary>
/// The additional data of this request serialized into bytes.
/// </summary>
public byte[] Body;
/// <summary>
/// Settings to customize this request's behaviour.
/// </summary>
public HttpOptions Options;
/// <summary>
/// Initialize a new instance of the <see cref="HttpRequest"/> class.
/// </summary>
public HttpRequest() {}
/// <summary>
/// Initialize a new instance of the <see cref="HttpRequest"/> class with the given parameters.
/// </summary>
/// <param name="method">
/// The HTTP method to use.
/// Valid methods are: DELETE, GET, PATCH, POST, PUT.
/// </param>
/// <param name="url">
/// The target url of the created request.
/// </param>
/// <param name="headers">
/// The headers to add to the request.
/// </param>
/// <param name="body">
/// The request's data serialized into bytes.
/// </param>
public HttpRequest(string method, string url, Dictionary<string, string> headers, byte[] body)
{
Method = method;
Url = url;
Headers = headers;
Body = body;
}
/// <summary>
/// Set the given <paramref name="method"/> to this request.
/// </summary>
/// <param name="method">
/// The HTTP method to use.
/// Valid methods are: DELETE, GET, PATCH, POST, PUT.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public HttpRequest SetMethod(string method)
{
Method = method;
return this;
}
/// <summary>
/// Set the given <paramref name="url"/> to this request.
/// </summary>
/// <param name="url">
/// The target url of the created request.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public HttpRequest SetUrl(string url)
{
Url = url;
return this;
}
/// <summary>
/// Add or update a header to this request using the given
/// <paramref name="key"/> and <paramref name="value"/>.
/// </summary>
/// <param name="key">
/// The header's key.
/// </param>
/// <param name="value">
/// The header's value.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public HttpRequest SetHeader(string key, string value)
{
if (Headers is null)
{
Headers = new Dictionary<string, string>(1);
}
Headers[key] = value;
return this;
}
/// <summary>
/// Set the given <paramref name="headers"/> to this request.
/// </summary>
/// <param name="headers">
/// The headers to add to the request.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public HttpRequest SetHeaders(Dictionary<string, string> headers)
{
Headers = headers;
return this;
}
/// <summary>
/// Set the given <paramref name="body"/> to this request.
/// </summary>
/// <param name="body">
/// The request's data serialized into bytes.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public HttpRequest SetBody(byte[] body)
{
Body = body;
return this;
}
/// <summary>
/// Set the given <paramref name="options"/> to this request.
/// </summary>
/// <param name="options">
/// The settings to customize the request's behaviour.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public HttpRequest SetOptions(HttpOptions options)
{
Options = options;
return this;
}
/// <summary>
/// Set the given <paramref name="redirectLimit"/> to this request.
/// </summary>
/// <param name="redirectLimit">
/// The number of redirects this request can follow without failing.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public HttpRequest SetRedirectLimit(int redirectLimit)
{
Options.RedirectLimit = redirectLimit;
return this;
}
/// <summary>
/// Set the given <paramref name="timeout"/> to this request.
/// </summary>
/// <param name="timeout">
/// The delay, in seconds, after which the request will
/// be considered a failure if it didn't have a response.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public HttpRequest SetTimeOutInSeconds(int timeout)
{
Options.RequestTimeoutInSeconds = timeout;
return this;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dfc2b9b5d2fe14b188e5ac23c3580d9e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,134 @@
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Utility extensions on <see cref="HttpRequest"/>.
/// </summary>
static class HttpRequestExtensions
{
/// <summary>
/// Set this method to "GET".
/// </summary>
/// <param name="self">
/// The request to update the method of.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public static HttpRequest AsGet(this HttpRequest self)
{
return self.SetMethod("GET");
}
/// <summary>
/// Set this method to "POST".
/// </summary>
/// <param name="self">
/// The request to update the method of.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public static HttpRequest AsPost(this HttpRequest self)
{
return self.SetMethod("POST");
}
/// <summary>
/// Set this method to "PUT".
/// </summary>
/// <param name="self">
/// The request to update the method of.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public static HttpRequest AsPut(this HttpRequest self)
{
return self.SetMethod("PUT");
}
/// <summary>
/// Set this method to "DELETE".
/// </summary>
/// <param name="self">
/// The request to update the method of.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public static HttpRequest AsDelete(this HttpRequest self)
{
return self.SetMethod("DELETE");
}
/// <summary>
/// Set this method to "PATCH".
/// </summary>
/// <param name="self">
/// The request to update the method of.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public static HttpRequest AsPatch(this HttpRequest self)
{
return self.SetMethod("PATCH");
}
/// <summary>
/// Set this method to "HEAD".
/// </summary>
/// <param name="self">
/// The request to update the method of.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public static HttpRequest AsHead(this HttpRequest self)
{
return self.SetMethod("HEAD");
}
/// <summary>
/// Set this method to "CONNECT".
/// </summary>
/// <param name="self">
/// The request to update the method of.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public static HttpRequest AsConnect(this HttpRequest self)
{
return self.SetMethod("CONNECT");
}
/// <summary>
/// Set this method to "OPTIONS".
/// </summary>
/// <param name="self">
/// The request to update the method of.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public static HttpRequest AsOptions(this HttpRequest self)
{
return self.SetMethod("OPTIONS");
}
/// <summary>
/// Set this method to "TRACE".
/// </summary>
/// <param name="self">
/// The request to update the method of.
/// </param>
/// <returns>
/// Return this request.
/// </returns>
public static HttpRequest AsTrace(this HttpRequest self)
{
return self.SetMethod("TRACE");
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f6735934f1934f448e5884d3ca69780
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,193 @@
using System.Collections.Generic;
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Contain all data from a server response to a <see cref="HttpRequest"/>.
/// </summary>
class HttpResponse
{
/// <summary>
/// The request at the origin of this response.
/// </summary>
public ReadOnlyHttpRequest Request;
/// <summary>
/// The headers additional information.
/// </summary>
public Dictionary<string, string> Headers;
/// <summary>
/// The date sent by the server serialized into bytes.
/// </summary>
public byte[] Data;
/// <summary>
/// The status code sent by the server.
/// </summary>
public long StatusCode;
/// <summary>
/// The error message if an error occured.
/// </summary>
public string ErrorMessage;
/// <summary>
/// If true, the request failed due to an HTTP error.
/// </summary>
public bool IsHttpError;
/// <summary>
/// If true, the request failed due to a connectivity error.
/// </summary>
public bool IsNetworkError;
/// <summary>
/// Set the given <paramref name="request"/> to this response.
/// </summary>
/// <param name="request">
/// The request at the origin of this response.
/// </param>
/// <returns>
/// Return this response.
/// </returns>
public HttpResponse SetRequest(HttpRequest request)
{
Request = new ReadOnlyHttpRequest(request);
return this;
}
/// <summary>
/// Set the given <paramref name="request"/> to this response.
/// </summary>
/// <param name="request">
/// A handle to the request at the origin of this response.
/// </param>
/// <returns>
/// Return this response.
/// </returns>
public HttpResponse SetRequest(ReadOnlyHttpRequest request)
{
Request = request;
return this;
}
/// <summary>
/// Add or update a header to this request using the given
/// <paramref name="key"/> and <paramref name="value"/>.
/// </summary>
/// <param name="key">
/// The header's key.
/// </param>
/// <param name="value">
/// The header's value.
/// </param>
/// <returns>
/// Return this response.
/// </returns>
public HttpResponse SetHeader(string key, string value)
{
Headers[key] = value;
return this;
}
/// <summary>
/// Set the given <paramref name="headers"/> to this response.
/// </summary>
/// <param name="headers">
/// The headers to add to the request.
/// </param>
/// <returns>
/// Return this response.
/// </returns>
public HttpResponse SetHeaders(Dictionary<string, string> headers)
{
Headers = headers;
return this;
}
/// <summary>
/// Set the given <paramref name="data"/> to this response.
/// </summary>
/// <param name="data">
/// The response's data serialized into bytes.
/// </param>
/// <returns>
/// Return this response.
/// </returns>
public HttpResponse SetData(byte[] data)
{
Data = data;
return this;
}
/// <summary>
/// Set the given <paramref name="statusCode"/> to this response.
/// </summary>
/// <param name="statusCode">
/// The status code sent by the server.
/// </param>
/// <returns>
/// Return this response.
/// </returns>
public HttpResponse SetStatusCode(long statusCode)
{
StatusCode = statusCode;
return this;
}
/// <summary>
/// Set the given <paramref name="errorMessage"/> to this response.
/// </summary>
/// <param name="errorMessage">
/// The error message if an error occured during the <see cref="Request"/> processing.
/// </param>
/// <returns>
/// Return this response.
/// </returns>
public HttpResponse SetErrorMessage(string errorMessage)
{
ErrorMessage = errorMessage;
return this;
}
/// <summary>
/// Set the given <paramref name="isHttpError"/> to this response.
/// </summary>
/// <param name="isHttpError">
/// A flag to determine if this response failed due to an HTTP error.
/// </param>
/// <returns>
/// Return this response.
/// </returns>
public HttpResponse SetIsHttpError(bool isHttpError)
{
IsHttpError = isHttpError;
return this;
}
/// <summary>
/// Set the given <paramref name="isNetworkError"/> to this response.
/// </summary>
/// <param name="isNetworkError">
/// A flag to determine if this response failed due to a connectivity error.
/// </param>
/// <returns>
/// Return this response.
/// </returns>
public HttpResponse SetIsNetworkError(bool isNetworkError)
{
IsNetworkError = isNetworkError;
return this;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f062e98fc9ade4f4faa8759ddbf79a98
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,65 @@
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Contract for objects able to send an HTTP request.
/// </summary>
interface IHttpClient : IServiceComponent
{
/// <summary>
/// Get the base URL to reach the service identified by the given <paramref name="serviceId"/>.
/// </summary>
/// <param name="serviceId">
/// The ID of the remote service to get the base URL for.
/// </param>
/// <returns>
/// Return the base URL for the service if it exists;
/// throw otherwise.
/// </returns>
string GetBaseUrlFor(string serviceId);
/// <summary>
/// Get the default options for requests targeting the service
/// identified by the given <paramref name="serviceId"/>.
/// </summary>
/// <param name="serviceId">
/// The ID of the remote service to get default options for.
/// </param>
/// <returns>
/// Return the default options for requests targeting the service if it exists;
/// throw otherwise.
/// </returns>
HttpOptions GetDefaultOptionsFor(string serviceId);
/// <summary>
/// Create a new <see cref="HttpRequest"/> targeting the service
/// identified by the given <paramref name="serviceId"/>.
/// Also set its default options.
/// </summary>
/// <param name="serviceId">
/// The ID of the remote service to create a request for.
/// </param>
/// <param name="resourcePath">
/// The path to the resource to act on.
/// </param>
/// <returns>
/// Return the created <see cref="HttpRequest"/> if the service exists.
/// </returns>
HttpRequest CreateRequestForService(string serviceId, string resourcePath);
/// <summary>
/// Send the given <paramref name="request"/>.
/// Note: The success of the returned operation only means that the request could be handled
/// gracefully; the request in itself can still fail (HTTP error or network error).
/// </summary>
/// <param name="request">
/// The request to send.
/// </param>
/// <returns>
/// Return a handle to monitor the progression of the request.
/// The operation's result will contain the server's response if the request was sent successfully.
/// </returns>
IAsyncOperation<ReadOnlyHttpResponse> Send(HttpRequest request);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 03a13814984de4f0b88ec94c7f6f1b58
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,35 @@
using System.Collections.Generic;
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Read-only handle to a <see cref="HttpRequest"/>.
/// </summary>
struct ReadOnlyHttpRequest
{
HttpRequest m_Request;
/// <summary>
/// Create a read-only handle to the given <paramref name="request"/>.
/// </summary>
/// <param name="request">
/// The request to create the read-only handle for.
/// </param>
public ReadOnlyHttpRequest(HttpRequest request)
{
m_Request = request;
}
/// <inheritdoc cref="HttpRequest.Method"/>
public string Method => m_Request.Method;
/// <inheritdoc cref="HttpRequest.Url"/>
public string Url => m_Request.Url;
/// <inheritdoc cref="HttpRequest.Headers"/>
public IReadOnlyDictionary<string, string> Headers => m_Request.Headers;
/// <inheritdoc cref="HttpRequest.Body"/>
public byte[] Body => m_Request.Body;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eafba3bdb53b34d70a61f2cf40a497ec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,47 @@
using System.Collections.Generic;
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Read-only handle to a <see cref="HttpResponse"/>.
/// </summary>
struct ReadOnlyHttpResponse
{
HttpResponse m_Response;
/// <summary>
/// Create a read-only handle to the given <paramref name="response"/>.
/// </summary>
/// <param name="response">
/// The response to create the read-only handle for.
/// </param>
public ReadOnlyHttpResponse(HttpResponse response)
{
m_Response = response;
}
/// <inheritdoc cref="HttpResponse.Request"/>
public ReadOnlyHttpRequest Request => m_Response.Request;
/// <inheritdoc cref="HttpResponse.Headers"/>
public IReadOnlyDictionary<string, string> Headers => m_Response.Headers;
/// <inheritdoc cref="HttpResponse.Data"/>
public byte[] Data => m_Response.Data;
/// <inheritdoc cref="HttpResponse.StatusCode"/>
public long StatusCode => m_Response.StatusCode;
/// <inheritdoc cref="HttpResponse.ErrorMessage"/>
/// <remarks>
/// Can be filled by the server for HTTP errors or by the local request manager for network errors.
/// </remarks>
public string ErrorMessage => m_Response.ErrorMessage;
/// <inheritdoc cref="HttpResponse.IsHttpError"/>
public bool IsHttpError => m_Response.IsHttpError;
/// <inheritdoc cref="HttpResponse.IsNetworkError"/>
public bool IsNetworkError => m_Response.IsNetworkError;
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 57789d1bf989e4a6da9126326213f6ad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 332ad2f567fa467f945149fb7fabb67e
timeCreated: 1646947789

View file

@ -0,0 +1,66 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Services.Core.Internal;
#if UNITY_2020_2_OR_NEWER
using UnityEngine.Scripting;
#endif
namespace Unity.Services.Qos.Internal
{
/// <summary>
/// An interface that allows access to QoS measurements. For use by other Operate packages through the Core
/// Services SDK.
/// </summary>
#if UNITY_2020_2_OR_NEWER
[RequireImplementors]
#endif
public interface IQosResults : IServiceComponent
{
/// <summary>
/// Gets sorted QoS measurements the specified service and regions.
/// </summary>
/// <remarks>
/// `GetSortedQosResultsAsync` doesn't consider the returned regions until applying the services and regions filters.
///
/// If you specify regions, it only includes those regions.
/// </remarks>
/// <param name="service">The service to query regions for QoS. `GetSortedQosResultsAsync` only uses measures
/// regions configured for the specified service.</param>
/// <param name="regions">The regions to query for QoS. If not null or empty, `GetSortedQosResultsAsync` only uses
/// regions in the intersection of the specified service and the specified regions for measurements.</param>
/// <returns>Returns the sorted list of QoS results, ordered from best to worst.</returns>
Task<IList<QosResult>> GetSortedQosResultsAsync(string service, IList<string> regions);
}
/// <summary>
/// Represents the results of QoS measurements for a given region.
/// </summary>
public struct QosResult
{
/// <summary>
/// The identifier for the service's region used in this set of QoS measurements.
/// </summary>
/// <value>A string containing the region name.
/// </value>
public string Region;
/// <summary>
/// Average latency of QoS measurements to the region.
/// </summary>
/// <remarks>
/// The latency is determined by measuring the time between sending a packet and receiving the response for that packet,
/// then taking the average for all responses received. Only packets for which a response was received are
/// considered in the calculation.
/// </remarks>
/// <value>A positive integer, in milliseconds.</value>
public int AverageLatencyMs;
/// <summary>
/// Percentage of packet loss observed in QoS measurements to the region.
/// </summary>
/// <remarks>
/// Packet loss is determined by counting the number of packets for which a response was received from the QoS server,
/// then taking the percentage based on the total number of packets sent.
/// </remarks>
/// <value>A positive flow value. The range is 0.0f - 1.0f (0 - 100%).</value>
public float PacketLossPercent;
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cec35b4f221f4ae69973858262c86db2
timeCreated: 1646947810

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a38057f3b0350493ca2bf521021d2c83
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,31 @@
using System;
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Scheduler.Internal
{
/// <summary>
/// Unity Service Scheduler to schedule actions on main thread.
/// </summary>
public interface IActionScheduler : IServiceComponent
{
/// <summary>
/// Schedules the action to be invoked on the main thead, on the first frame that occurs after the given delay in seconds
/// </summary>
/// <param name="action">
/// Action to be scheduled.
/// </param>
/// <param name="delaySeconds">
/// time in seconds to delay execute action
/// </param>
/// <returns>unique Id for the scheduled action</returns>
long ScheduleAction(Action action, double delaySeconds = 0);
/// <summary>
/// Removes all instances of the given action from the queue
/// </summary>
/// <param name="actionId">
/// unique Id for action to be canceled.
/// </param>
void CancelAction(long actionId);
}
}

Some files were not shown because too many files have changed in this diff Show more