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,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);
}
}

View file

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

View file

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

View file

@ -0,0 +1,24 @@
using System.Collections.Generic;
namespace Unity.Services.Core.Telemetry.Internal
{
/// <summary>
/// Object used to send diagnostic events to the backend.
/// </summary>
public interface IDiagnostics
{
/// <summary>
/// Send a diagnostic event to the telemetry service to report unexpected behaviour.
/// </summary>
/// <param name="name">
/// Name of the event.
/// </param>
/// <param name="message">
/// An error message describing what error occured.
/// </param>
/// <param name="tags">
/// Event tags.
/// </param>
void SendDiagnostic(string name, string message, IDictionary<string, string> tags = null);
}
}

View file

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

View file

@ -0,0 +1,12 @@
using System.Threading.Tasks;
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Telemetry.Internal
{
interface IDiagnosticsComponentProvider
{
Task<IDiagnosticsFactory> CreateDiagnosticsComponents();
Task<string> GetSerializedProjectConfigurationAsync();
}
}

View file

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

View file

@ -0,0 +1,28 @@
using System.Collections.Generic;
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Telemetry.Internal
{
/// <summary>
/// Component to get or create the proper <see cref="IDiagnostics"/> for a given package.
/// </summary>
public interface IDiagnosticsFactory : IServiceComponent
{
/// <summary>
/// All tags shared among all diagnostics events generated by <see cref="IDiagnostics"/> created by this factory.
/// </summary>
IReadOnlyDictionary<string, string> CommonTags { get; }
/// <summary>
/// Create a <see cref="IDiagnostics"/> setup with common tags for the given <paramref name="packageName"/>.
/// </summary>
/// <param name="packageName">
/// The name of the package that will use the created <see cref="IDiagnostics"/> to send diagnostic events.
/// Example value: "com.unity.services.core"
/// </param>
/// <returns>
/// Return a <see cref="IDiagnostics"/> setup with common tags for the given <paramref name="packageName"/>.
/// </returns>
IDiagnostics Create(string packageName);
}
}

View file

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

View file

@ -0,0 +1,52 @@
using System.Collections.Generic;
namespace Unity.Services.Core.Telemetry.Internal
{
/// <summary>
/// Object used to send metrics events to the backend.
/// </summary>
public interface IMetrics
{
/// <summary>
/// Send a metric that can arbitrarily go up or down to the telemetry service.
/// </summary>
/// <param name="name">
/// Name of the event.
/// </param>
/// <param name="value">
/// Value of the metric.
/// </param>
/// <param name="tags">
/// Event tags.
/// </param>
void SendGaugeMetric(string name, double value = 0, IDictionary<string, string> tags = null);
/// <summary>
/// Send a metric that lasts over time to the telemetry service.
/// </summary>
/// <param name="name">
/// Name of the event.
/// </param>
/// <param name="time">
/// Duration of the operation the event is tracking.
/// </param>
/// <param name="tags">
/// Event tags.
/// </param>
void SendHistogramMetric(string name, double time, IDictionary<string, string> tags = null);
/// <summary>
/// Send a metric that can only be incremented to the telemetry service.
/// </summary>
/// <param name="name">
/// Name of the event.
/// </param>
/// <param name="value">
/// Value of the metric.
/// </param>
/// <param name="tags">
/// Event tags.
/// </param>
void SendSumMetric(string name, double value = 1, IDictionary<string, string> tags = null);
}
}

View file

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

View file

@ -0,0 +1,28 @@
using System.Collections.Generic;
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Telemetry.Internal
{
/// <summary>
/// Component to get or create the proper <see cref="IMetrics"/> for a given package.
/// </summary>
public interface IMetricsFactory : IServiceComponent
{
/// <summary>
/// All tags shared among all metrics events generated by <see cref="IMetrics"/> created by this factory.
/// </summary>
IReadOnlyDictionary<string, string> CommonTags { get; }
/// <summary>
/// Create a <see cref="IMetrics"/> setup with common tags for the given <paramref name="packageName"/>.
/// </summary>
/// <param name="packageName">
/// The name of the package that will use the created <see cref="IMetrics"/> to send metric events.
/// Example value: "com.unity.services.core"
/// </param>
/// <returns>
/// Return a <see cref="IMetrics"/> setup with common tags for the given <paramref name="packageName"/>.
/// </returns>
IMetrics Create(string packageName);
}
}

View file

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

View file

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

View file

@ -0,0 +1,136 @@
using System;
using System.Threading.Tasks;
using Unity.Services.Core.Internal;
using NotNull = JetBrains.Annotations.NotNullAttribute;
namespace Unity.Services.Core.Threading.Internal
{
/// <summary>
/// This component is an utility to simplify working with the Unity thread.
/// </summary>
public interface IUnityThreadUtils : IServiceComponent
{
/// <summary>
/// Check if the calling thread is the Unity thread.
/// </summary>
bool IsRunningOnUnityThread { get; }
/// <summary>
/// Create a task out of the given <paramref name="action"/> that will be invoked on the Unity thread.
/// </summary>
/// <param name="action">
/// The action to invoke on the Unity thread.
/// </param>
/// <returns>
/// Return the created task.
/// </returns>
Task PostAsync([NotNull] Action action);
/// <summary>
/// Create a task out of the given <paramref name="action"/> that will be invoked on the Unity thread.
/// </summary>
/// <param name="action">
/// The action to invoke on the Unity thread.
/// <paramref name="state"/> will be passed as its argument.
/// </param>
/// <param name="state">
/// The captured state to pass to <paramref name="action"/> when invoking it.
/// </param>
/// <returns>
/// Return the created task.
/// </returns>
Task PostAsync([NotNull] Action<object> action, object state);
/// <summary>
/// Create a task out of the given <paramref name="action"/> that will be invoked on the Unity thread.
/// </summary>
/// <param name="action">
/// The action to invoke on the Unity thread.
/// </param>
/// <typeparam name="T">
/// The type of the return of the invoked action.
/// Can be any type.
/// </typeparam>
/// <returns>
/// Return the created task.
/// </returns>
Task<T> PostAsync<T>([NotNull] Func<T> action);
/// <summary>
/// Create a task out of the given <paramref name="action"/> that will be invoked on the Unity thread.
/// </summary>
/// <param name="action">
/// The action to invoke on the Unity thread.
/// <paramref name="state"/> will be passed as its argument.
/// </param>
/// <param name="state">
/// The captured state to pass to <paramref name="action"/> when invoking it.
/// </param>
/// <typeparam name="T">
/// The type of the return of the invoked action.
/// Can be any type.
/// </typeparam>
/// <returns>
/// Return the created task.
/// </returns>
Task<T> PostAsync<T>([NotNull] Func<object, T> action, object state);
/// <summary>
/// Execute the given <paramref name="action"/> on the Unity thread.
/// Wait for the execution to finish before resuming this thread.
/// </summary>
/// <param name="action">
/// The action to invoke on the Unity thread.
/// </param>
void Send([NotNull] Action action);
/// <summary>
/// Execute the given <paramref name="action"/> on the Unity thread.
/// Wait for the execution to finish before resuming this thread.
/// </summary>
/// <param name="action">
/// The action to invoke on the Unity thread.
/// <paramref name="state"/> will be passed as its argument.
/// </param>
/// <param name="state">
/// The captured state to pass to <paramref name="action"/> when invoking it.
/// </param>
void Send([NotNull] Action<object> action, object state);
/// <summary>
/// Execute the given <paramref name="action"/> on the Unity thread.
/// Wait for the execution to finish before resuming this thread.
/// </summary>
/// <param name="action">
/// The action to invoke on the Unity thread.
/// </param>
/// <typeparam name="T">
/// The type of the return of the invoked action.
/// Can be any type.
/// </typeparam>
/// <returns>
/// Return what the action returned.
/// </returns>
T Send<T>([NotNull] Func<T> action);
/// <summary>
/// Execute the given <paramref name="action"/> on the Unity thread.
/// Wait for the execution to finish before resuming this thread.
/// </summary>
/// <param name="action">
/// The action to invoke on the Unity thread.
/// <paramref name="state"/> will be passed as its argument.
/// </param>
/// <param name="state">
/// The captured state to pass to <paramref name="action"/> when invoking it.
/// </param>
/// <typeparam name="T">
/// The type of the return of the invoked action.
/// Can be any type.
/// </typeparam>
/// <returns>
/// Return what the action returned.
/// </returns>
T Send<T>([NotNull] Func<object, T> action, object state);
}
}

View file

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

View file

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

View file

@ -0,0 +1,26 @@
using Unity.Services.Core.Internal;
#if UNITY_2020_2_OR_NEWER
using UnityEngine.Scripting;
#endif
namespace Unity.Services.Vivox.Internal
{
/// <summary>
/// Provides utilities for performing simple Vivox actions or overriding
/// the <see cref="IVivoxTokenProviderInternal"/> with a custom implementation.
/// </summary>
#if UNITY_2020_2_OR_NEWER
[RequireImplementors]
#endif
public interface IVivox : IServiceComponent
{
/// <summary>
/// Registers an <see cref="IVivoxTokenProviderInternal"/> that will be used as the primary
/// token generator for all Vivox actions.
/// </summary>
/// <param name="tokenProvider">
/// Token provider to register.
/// </param>
void RegisterTokenProvider(IVivoxTokenProviderInternal tokenProvider);
}
}

View file

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

View file

@ -0,0 +1,52 @@
using System;
using System.Threading.Tasks;
namespace Unity.Services.Vivox.Internal
{
/// <summary>
/// Must be implemented by the <see cref="IVivox.RegisterTokenProvider(IVivoxTokenProviderInternal)"/> caller.
/// This object's responsibility is to provide an overridable implementation that will generate
/// tokens for Vivox actions.
/// </summary>
public interface IVivoxTokenProviderInternal
{
/// <summary>
/// This async method should implement the necessary steps to providing a valid Vivox token.
/// After registration, this method will automatically be called whenever a token needs to
/// be generated for a particular action. (e.g. login, channel join, mute).
/// This token generation method will not be used if a developer provides their own
/// IVivoxTokenProvider implementation to the Vivox service.
/// If the requested action is a login to the Vivox service we will use the UAS token for
/// that instead of this method as well.
/// </summary>
/// <param name="issuer">
/// Id of a title.
/// Provided as part of the credentials delivered upon creating a project in the Unity Dashboard
/// and enabling Vivox.
/// </param>
/// <param name="expiration">
/// When the token should expire.
/// </param>
/// <param name="userUri">
/// Id of the target for actions such as muting and blocking.
/// </param>
/// <param name="action">
/// The action for which a token is requested.
/// e.g.: "login", "join", ...
/// </param>
/// <param name="conferenceUri">
/// Id if the conference requesting the token.
/// </param>
/// <param name="fromUserUri">
/// Id of the user requesting the token.
/// </param>
/// <param name="realm">
/// Domain for which the token should be created.
/// </param>
/// <returns>
/// A Vivox token string.
/// </returns>
Task<string> GetTokenAsync(string issuer = null, TimeSpan? expiration = null, string userUri = null,
string action = null, string conferenceUri = null, string fromUserUri = null, string realm = null);
}
}

View file

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

View file

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

View file

@ -0,0 +1,17 @@
namespace Unity.Services.Wire.Internal
{
/// <summary>
/// This structure represents the necessary data to perform a Wire subscription to an <see cref="IChannel"/>
/// </summary>
public struct ChannelToken
{
/// <summary>
/// This is a string identifying a Channel on which a service publishes messages.
/// </summary>
public string ChannelName;
/// <summary>
/// This is an authorization token emitted by the service who owns the Channel for this specific UAS Id.
/// </summary>
public string Token;
}
}

View file

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

View file

@ -0,0 +1,63 @@
using System;
using System.Threading.Tasks;
namespace Unity.Services.Wire.Internal
{
/// <summary>
/// Channel object. Use <see cref="IWire.CreateChannel(IChannelTokenProvider)"/>
/// to construct one. This object allows the subscription to a channel.
/// </summary>
public interface IChannel : IDisposable
{
/// <summary>
/// Handler called each time the channel receives a message.
/// </summary>
event Action<string> MessageReceived;
/// <summary>
/// Handler called each time the channel receives a binary message.
/// </summary>
event Action<byte[]> BinaryMessageReceived;
/// <summary>
/// Handler called if the subscription gets terminated by the Wire server.
/// </summary>
event Action KickReceived;
/// <summary>
/// Handler called whenever the subscription reliability changes.
/// </summary>
event Action<SubscriptionState> NewStateReceived;
/// <summary>
/// Handler called whenever the subscription encounters an error.
/// A description of the error is passed as an argument.
/// </summary>
event Action<string> ErrorReceived;
/// <summary>
/// SubscribeAsync will subscribe to the channel.
/// Possible error codes are:
/// * 23002 -> "CommandFailed"
/// * 23003 -> "ConnectionFailed"
/// * 23004 -> "InvalidToken"
/// * 23005 -> "InvalidChannelName"
/// * 23006 -> "TokenRetrieverFailed"
/// * 23007 -> "Unauthorized"
/// * 23008 -> "AlreadySubscribed"
/// </summary>
/// <returns>An awaitable task.</returns>
/// <exception cref="RequestFailedException"/>
Task SubscribeAsync();
/// <summary>
/// UnsubscribeAsync will stop the subscription, effective immediately.
/// Possible error codes are:
/// * 23002 -> "CommandFailed"
/// * 23009 -> "AlreadyUnsubscribed"
/// </summary>
/// <returns>An awaitable task.</returns>
/// <exception cref="RequestFailedException"/>
Task UnsubscribeAsync();
}
}

View file

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

View file

@ -0,0 +1,19 @@
using System.Threading.Tasks;
namespace Unity.Services.Wire.Internal
{
/// <summary>
/// Must be implemented by the <see cref="IWire.CreateChannel(IChannelTokenProvider)"/> caller.
/// This object responsibility is to provide an async method that returns a <see cref="ChannelToken"/> structure.
/// </summary>
public interface IChannelTokenProvider
{
/// <summary>
/// This async method should implement whetever network transaction necessary to retrieve a token enabling a Wire subscription.
/// This function can be called by the Wire SDK multiple times during the lifetime of the subscription.
/// For example, whenever the token needs to be refreshed.
/// </summary>
/// <returns>A <see cref="ChannelToken"/> structure to be used at subscription time.</returns>
Task<ChannelToken> GetTokenAsync();
}
}

View file

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

View file

@ -0,0 +1,26 @@
using System;
using Unity.Services.Core.Internal;
#if UNITY_2020_2_OR_NEWER
using UnityEngine.Scripting;
#endif
namespace Unity.Services.Wire.Internal
{
/// <summary>
/// IWire allows the creation of disposable <see cref="IChannel"/> objects.
/// </summary>
#if UNITY_2020_2_OR_NEWER
[RequireImplementors]
#endif
public interface IWire : IServiceComponent
{
/// <summary>
/// CreateChannel is a <see cref="IChannel"/> factory. It will generate an object enabling the subscription to a Wire channel.
/// </summary>
/// <param name="tokenProvider">Will be used to obtain a subscription token whenever the user calls <see cref="IChannel.SubscribeAsync"/>
/// or Wire might choose to use it whenever a refreshed token is needed. Make sure that this <see cref="IChannelTokenProvider"/> can never provide
/// an outdated or bad token.</param>
/// <returns>A <see cref="IChannel"/> object.</returns>
IChannel CreateChannel(IChannelTokenProvider tokenProvider);
}
}

View file

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

View file

@ -0,0 +1,33 @@
using System;
namespace Unity.Services.Wire.Internal
{
/// <summary>
/// The subscription current state.
/// </summary>
public enum SubscriptionState
{
/// <summary>
/// The subscription is inactive.
/// </summary>
Unsubscribed,
/// <summary>
/// The subscription is active and synchronized to the server. You can trust that the last message received
/// from the subscription is up to date.
/// </summary>
Synced,
/// <summary>
/// A connectivity issue prevents Wire from receiving update on this active subscription. As soon as Wire
/// has reconnected, the subscription will receive the missing messages.
/// </summary>
Unsynced,
/// <summary>
/// The subscription encountered an error and is not active.
/// </summary>
Error,
/// <summary>
/// Wire is getting a token then sending a request to Wire to subscribe to a channel.
/// </summary>
Subscribing,
}
}

View file

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

View file

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

View file

@ -0,0 +1,34 @@
using System;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace Unity.Services.Core.Internal
{
static class CoreLogger
{
internal const string Tag = "[ServicesCore]";
internal const string VerboseLoggingDefine = "ENABLE_UNITY_SERVICES_CORE_VERBOSE_LOGGING";
const string k_TelemetryLoggingDefine = "ENABLE_UNITY_SERVICES_CORE_TELEMETRY_LOGGING";
public static void Log(object message) => Debug.unityLogger.Log(Tag, message);
public static void LogWarning(object message) => Debug.unityLogger.LogWarning(Tag, message);
public static void LogError(object message) => Debug.unityLogger.LogError(Tag, message);
public static void LogException(Exception exception) =>
Debug.unityLogger.Log(LogType.Exception, Tag, exception);
[Conditional("UNITY_ASSERTIONS")]
public static void LogAssertion(object message) => Debug.unityLogger.Log(LogType.Assert, Tag, message);
#if !ENABLE_UNITY_SERVICES_VERBOSE_LOGGING
[Conditional(VerboseLoggingDefine)]
#endif
public static void LogVerbose(object message) => Debug.unityLogger.Log(Tag, message);
#if !ENABLE_UNITY_SERVICES_TELEMETRY_LOGGING
[Conditional(k_TelemetryLoggingDefine)]
#endif
public static void LogTelemetry(object message) => Debug.unityLogger.Log(Tag, message);
}
}

View file

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

View file

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

View file

@ -0,0 +1,23 @@
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Exception to use two registered <see cref="IInitializablePackage"/> depend on the other.
/// </summary>
public class CircularDependencyException : ServicesInitializationException
{
/// <summary>
/// Initialize a new instance of the <see cref="ServicesInitializationException" /> class.
/// </summary>
public CircularDependencyException() {}
/// <summary>
/// Initialize a new instance of the <see cref="ServicesInitializationException" />
/// class with a specified error message.
/// </summary>
/// <param name="message">
/// The error message that explains the reason for the exception.
/// </param>
public CircularDependencyException(string message)
: base(message) {}
}
}

View file

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

View file

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

View file

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using NotNull = JetBrains.Annotations.NotNullAttribute;
namespace Unity.Services.Core.Internal
{
class ComponentRegistry : IComponentRegistry
{
/// <summary>
/// Key: Hash code of a <see cref="IServiceComponent"/> type.
/// Value: Component instance.
/// </summary>
[NotNull]
internal Dictionary<int, IServiceComponent> ComponentTypeHashToInstance { get; }
public ComponentRegistry(
[NotNull] Dictionary<int, IServiceComponent> componentTypeHashToInstance)
{
ComponentTypeHashToInstance = componentTypeHashToInstance;
}
public void RegisterServiceComponent<TComponent>(TComponent component)
where TComponent : IServiceComponent
{
var componentType = typeof(TComponent);
// This check is to avoid passing the component without specifying the interface type as a generic argument.
if (component.GetType() == componentType)
{
throw new ArgumentException("Interface type of component not specified.");
}
var componentTypeHash = componentType.GetHashCode();
if (IsComponentTypeRegistered(componentTypeHash))
{
throw new InvalidOperationException(
$"A component with the type {componentType.FullName} has already been registered.");
}
ComponentTypeHashToInstance[componentTypeHash] = component;
}
public TComponent GetServiceComponent<TComponent>()
where TComponent : IServiceComponent
{
var componentType = typeof(TComponent);
if (!ComponentTypeHashToInstance.TryGetValue(componentType.GetHashCode(), out var component)
|| component is MissingComponent)
{
throw new KeyNotFoundException($"There is no component `{componentType.Name}` registered. " +
"Are you missing a package?");
}
return (TComponent)component;
}
bool IsComponentTypeRegistered(int componentTypeHash)
{
return ComponentTypeHashToInstance.TryGetValue(componentTypeHash, out var storedComponent)
&& !(storedComponent is null)
&& !(storedComponent is MissingComponent);
}
public void ResetProvidedComponents(IDictionary<int, IServiceComponent> componentTypeHashToInstance)
{
ComponentTypeHashToInstance.Clear();
ComponentTypeHashToInstance.MergeAllowOverride(componentTypeHashToInstance);
}
}
}

View file

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

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