浏览代码

Package updates happened, so I need to update the packages, but I don't want to bring in the branch with the existing rate limiting workaround at the same time. So, this is its own changeset. This should match the state of the closed_beta_package_update branch.

/main/staging/rate_limit_data
nathaniel.buck@unity3d.com 3 年前
当前提交
2bd692a3
共有 238 个文件被更改,包括 723 次插入693 次删除
  1. 1
      Assets/Scripts/Lobby/LobbyAPIInterface.cs
  2. 16
      Packages/com.unity.services.authentication/CHANGELOG.md
  3. 20
      Packages/com.unity.services.authentication/Editor/AuthenticationAdminClient.cs
  4. 4
      Packages/com.unity.services.authentication/Editor/AuthenticationAdminNetworkClient.cs
  5. 1
      Packages/com.unity.services.authentication/Editor/AuthenticationIdentifier.cs
  6. 2
      Packages/com.unity.services.authentication/Editor/AuthenticationSettingsElement.cs
  7. 3
      Packages/com.unity.services.authentication/Editor/IAuthenticationAdminClient.cs
  8. 2
      Packages/com.unity.services.authentication/Editor/IdProviderElement.cs
  9. 2
      Packages/com.unity.services.authentication/LICENSE.md
  10. 2
      Packages/com.unity.services.authentication/README.md
  11. 26
      Packages/com.unity.services.authentication/Runtime/AuthenticationAsyncOperation.cs
  12. 49
      Packages/com.unity.services.authentication/Runtime/AuthenticationNetworkClient.cs
  13. 10
      Packages/com.unity.services.authentication/Runtime/AuthenticationService.cs
  14. 53
      Packages/com.unity.services.authentication/Runtime/AuthenticationServiceInternal.cs
  15. 2
      Packages/com.unity.services.authentication/Runtime/Core/AccessTokenComponent.cs
  16. 20
      Packages/com.unity.services.authentication/Runtime/Core/AuthenticationPackageInitializer.cs
  17. 1
      Packages/com.unity.services.authentication/Runtime/Core/PlayerIdComponent.cs
  18. 100
      Packages/com.unity.services.authentication/Runtime/IAuthenticationService.cs
  19. 14
      Packages/com.unity.services.authentication/Runtime/JwtDecoder.cs
  20. 15
      Packages/com.unity.services.authentication/Runtime/Unity.Services.Authentication.api
  21. 3
      Packages/com.unity.services.authentication/Runtime/Unity.Services.Authentication.asmdef
  22. 164
      Packages/com.unity.services.authentication/Runtime/Utilities/Logger.cs
  23. 14
      Packages/com.unity.services.authentication/Runtime/Utilities/Logger.cs.meta
  24. 11
      Packages/com.unity.services.authentication/Runtime/Utilities/NetworkingUtilities.cs
  25. 34
      Packages/com.unity.services.authentication/Runtime/Utilities/WebRequest.cs
  26. 10
      Packages/com.unity.services.authentication/package.json
  27. 27
      Packages/com.unity.services.core/CHANGELOG.md
  28. 6
      Packages/com.unity.services.core/Editor/Core/BackendHelpers/JsonHelper.cs
  29. 26
      Packages/com.unity.services.core/Editor/Core/BackendHelpers/UnityWebRequestHelper.cs
  30. 33
      Packages/com.unity.services.core/Editor/Core/Configuration/ProjectConfigurationBuilder.cs
  31. 3
      Packages/com.unity.services.core/Editor/Core/Configuration/Unity.Services.Core.Configuration.Editor.asmdef
  32. 12
      Packages/com.unity.services.core/Editor/Core/EditorGameService/DefaultCdnConfiguredEndpoint.cs
  33. 1
      Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceDashboardHelper.cs
  34. 2
      Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceFlagEnabler.cs
  35. 10
      Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceRegistry.cs
  36. 8
      Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceRemoteConfiguration.cs
  37. 29
      Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceSettingsProvider.cs
  38. 33
      Packages/com.unity.services.core/Editor/Core/EditorGameService/ServiceFlagEndpoint.cs
  39. 2
      Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/IServiceFlagRequest.cs
  40. 2
      Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/IServiceFlags.cs
  41. 6
      Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/ProjectStateHelper.cs
  42. 18
      Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/ServiceFlagRequest.cs
  43. 10
      Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/ServiceFlags.cs
  44. 2
      Packages/com.unity.services.core/Editor/Core/UserRoleManagement/IUserRoleRequest.cs
  45. 5
      Packages/com.unity.services.core/Editor/Core/UserRoleManagement/UserRoleHandler.cs
  46. 58
      Packages/com.unity.services.core/Editor/Core/UserRoleManagement/UserRoleRequest.cs
  47. 3
      Packages/com.unity.services.core/Runtime/Configuration/ConfigurationCollectionHelper.cs
  48. 3
      Packages/com.unity.services.core/Runtime/Configuration/ConfigurationUtils.cs
  49. 1
      Packages/com.unity.services.core/Runtime/Configuration/ProjectConfiguration.cs
  50. 2
      Packages/com.unity.services.core/Runtime/Configuration/Utils/StreamingAssetsUtils.cs
  51. 2
      Packages/com.unity.services.core/Runtime/Configuration/Utils/UnityWebRequestUtils.cs
  52. 2
      Packages/com.unity.services.core/Runtime/Configuration/StreamingAssetsConfigurationLoader.cs
  53. 3
      Packages/com.unity.services.core/Runtime/Core.Internal/AssemblyInfo.cs
  54. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperation.cs
  55. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperationAwaiter.cs
  56. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperationBase.cs
  57. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperationExtensions.cs
  58. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperationStatus.cs
  59. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/IAsyncOperation.cs
  60. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/IAsyncOperationAwaiter.cs
  61. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/TaskAsyncOperation.cs
  62. 4
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Authentication/IAccessToken.cs
  63. 4
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Authentication/IPlayerId.cs
  64. 4
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Configuration/IProjectConfiguration.cs
  65. 5
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Device/IInstallationId.cs
  66. 4
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Environments/IEnvironments.cs
  67. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/HttpOptions.cs
  68. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/HttpRequest.cs
  69. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/HttpRequestExtensions.cs
  70. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/HttpResponse.cs
  71. 4
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/IHttpClient.cs
  72. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/ReadOnlyHttpRequest.cs
  73. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/ReadOnlyHttpResponse.cs
  74. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Registry/CircularDependencyException.cs
  75. 14
      Packages/com.unity.services.core/Runtime/Core.Internal/Registry/CoreRegistration.cs
  76. 169
      Packages/com.unity.services.core/Runtime/Core.Internal/Registry/CoreRegistry.cs
  77. 8
      Packages/com.unity.services.core/Runtime/Core.Internal/Registry/CoreRegistryInitializer.cs
  78. 7
      Packages/com.unity.services.core/Runtime/Core.Internal/Registry/DependencyTree.cs
  79. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Registry/DependencyTreeInitializeOrderSorter.cs
  80. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Registry/IInitializablePackage.cs
  81. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Registry/IServiceComponent.cs
  82. 2
      Packages/com.unity.services.core/Runtime/Core.Internal/Registry/MissingComponent.cs
  83. 80
      Packages/com.unity.services.core/Runtime/Core.Internal/Unity.Services.Core.Internal.api
  84. 16
      Packages/com.unity.services.core/Runtime/Core.Internal/UnityServicesInitializer.cs
  85. 60
      Packages/com.unity.services.core/Runtime/Core.Internal/UnityServicesInternal.cs
  86. 19
      Packages/com.unity.services.core/Runtime/Core/Unity.Services.Core.api
  87. 2
      Packages/com.unity.services.core/Runtime/Core/Unity.Services.Core.api.meta
  88. 8
      Packages/com.unity.services.core/Runtime/Core/UnityServices.cs
  89. 12
      Packages/com.unity.services.core/Runtime/Device/UserIdProviders/AndroidUtils.cs
  90. 2
      Packages/com.unity.services.core/Runtime/Device/UserIdProviders/NSUserDefaults.cs
  91. 4
      Packages/com.unity.services.core/Runtime/Device/UserIdProviders/UnityAdsIdentifier.cs
  92. 2
      Packages/com.unity.services.core/Runtime/Device/UserIdProviders/UnityAnalyticsIdentifier.cs
  93. 2
      Packages/com.unity.services.core/Runtime/Device/UserIdProviders/IUserIdentifierProvider.cs
  94. 7
      Packages/com.unity.services.core/Runtime/Environments/Unity.Services.Core.Environments.api
  95. 8
      Packages/com.unity.services.core/Runtime/Environments/Unity.Services.Core.Environments.asmdef
  96. 1
      Packages/com.unity.services.core/Runtime/Networking/HttpServiceConfig.cs
  97. 2
      Packages/com.unity.services.core/Runtime/Networking/UnityWebRequestClient.cs
  98. 28
      Packages/com.unity.services.core/Runtime/Registration/CorePackageInitializer.cs
  99. 3
      Packages/com.unity.services.core/Runtime/Registration/Unity.Services.Core.Registration.asmdef
  100. 11
      Packages/com.unity.services.core/package.json

1
Assets/Scripts/Lobby/LobbyAPIInterface.cs


using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Services.Lobbies;
using Unity.Services.Lobbies.Lobby;
using Unity.Services.Lobbies.Models;
namespace LobbyRelaySample.lobby

16
Packages/com.unity.services.authentication/CHANGELOG.md


## [Unreleased]
## [0.4.0-preview] - 2021-06-16
## [0.7.1-preview] - 2021-07-22
### Changed
- Updated the core SDK dependency to latest version.
## [0.7.0-preview] - 2021-07-22
### Changed
- Updated the core SDK dependency to latest version.
### Added
- Add missing xmldoc for the public functions.
## [0.6.0-preview] - 2021-07-15
### Added
- Add support for Unity Environments
## [0.5.0-preview] - 2021-06-16
### Changed
- Remove `SetOAuthClient()` as the authentication flow is simplified.
- Updated the initialization code to initialize with `UnityServices.Initialize()`

20
Packages/com.unity.services.authentication/Editor/AuthenticationAdminClient.cs


using Unity.Services.Authentication.Editor.Models;
using Unity.Services.Authentication.Models;
using Unity.Services.Authentication.Utilities;
using Unity.Services.Core;
using Unity.Services.Core.Internal;
using UnityEngine;
using ILogger = Unity.Services.Authentication.Utilities.ILogger;
using Logger = Unity.Services.Authentication.Utilities.Logger;
[assembly: InternalsVisibleTo("Unity.Services.Authentication.Editor.Tests")]

static IAuthenticationAdminClient AuthenticationAdminClient()
{
var logger = new Logger("[Authentication]");
INetworkingUtilities networkUtilities = new NetworkingUtilities(null, logger);
INetworkingUtilities networkUtilities = new NetworkingUtilities(null);
networkUtilities,
logger);
networkUtilities);
return new AuthenticationAdminClient(logger, networkClient);
return new AuthenticationAdminClient(networkClient);
}
// GetOrganizationId will gets the organization id associated with this Unity project.

{
string m_IdDomain;
IAuthenticationAdminNetworkClient m_AuthenticationAdminNetworkClient;
ILogger m_Logger;
string m_orgForeignKey;
string m_servicesGatewayToken;

AuthenticationAdmin
}
public AuthenticationAdminClient(ILogger logger, IAuthenticationAdminNetworkClient networkClient, string genesisToken = "")
public AuthenticationAdminClient(IAuthenticationAdminNetworkClient networkClient, string genesisToken = "")
m_Logger = logger;
m_AuthenticationAdminNetworkClient = networkClient;
m_genesisToken = genesisToken;
}

asyncOp.Fail(new AuthenticationException(AuthenticationError.NetworkError));
return true;
}
m_Logger?.Error("Error message: " + request.ErrorMessage);
Logger.LogError("Error message: " + request.ErrorMessage);
try
{

}
catch (JsonException ex)
{
Logger.LogException(ex);
Logger.LogException(ex);
asyncOp.Fail(new AuthenticationException(AuthenticationError.UnknownError, "Unknown error deserializing server response: " + request.ErrorMessage));
}

4
Packages/com.unity.services.authentication/Editor/AuthenticationAdminNetworkClient.cs


using Unity.Services.Authentication.Editor.Models;
using Unity.Services.Authentication.Utilities;
using UnityEngine;
using ILogger = Unity.Services.Authentication.Utilities.ILogger;
namespace Unity.Services.Authentication.Editor
{

internal AuthenticationAdminNetworkClient(string servicesGatewayHost,
string organizationId,
string projectId,
INetworkingUtilities networkClient,
ILogger logger)
INetworkingUtilities networkClient)
{
m_ServicesGatewayHost = servicesGatewayHost;
m_OrganizationId = organizationId;

1
Packages/com.unity.services.authentication/Editor/AuthenticationIdentifier.cs


/// <summary>
/// Key for the Authentication package
/// </summary>
/// <returns>The identifier of the game service.</returns>
public string GetKey() => "Authentication";
}
}

2
Packages/com.unity.services.authentication/Editor/AuthenticationSettingsElement.cs


using System;
using System.Collections.Generic;
using Unity.Services.Authentication.Editor.Models;
using Unity.Services.Core;
using Unity.Services.Core.Internal;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;

3
Packages/com.unity.services.authentication/Editor/IAuthenticationAdminClient.cs


using System;
using Unity.Services.Core;
using Unity.Services.Core.Internal;
namespace Unity.Services.Authentication.Editor
{

2
Packages/com.unity.services.authentication/Editor/IdProviderElement.cs


using System;
using System.Collections.Generic;
using Unity.Services.Authentication.Editor.Models;
using Unity.Services.Core;
using Unity.Services.Core.Internal;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

2
Packages/com.unity.services.authentication/LICENSE.md


This software is subject to, and made available under, the Unity Operate Terms of Service (see https://unity3d.com/legal/one-operate-services-terms-of-service), and is an "Operate Service" as defined therein.
Unless expressly provided otherwise, the software under this license is made available strictly on an "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the terms of service for details on these and other terms and conditions.
Unless expressly provided otherwise, the software under this license is made available strictly on an "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the terms of service for details on these and other terms and conditions.

2
Packages/com.unity.services.authentication/README.md


## Integration
The Authentication SDK is currently available on the UPM Candidates Repository. You will need to add the UPM Candidates Registry (https://artifactory.prd.it.unity3d.com/artifactory/api/npm/upm-candidates) as a Scoped Registry to your project. Once you have done that, you can add the package `com.unity.services.authentication` with the latest version: `0.5.0-preview`.
The Authentication SDK is currently available on the UPM Candidates Repository. You will need to add the UPM Candidates Registry (https://artifactory.prd.it.unity3d.com/artifactory/api/npm/upm-candidates) as a Scoped Registry to your project. Once you have done that, you can add the package `com.unity.services.authentication` with the latest version: `0.7.1-preview`.
Once you have installed the Authentication package, you must link your Unity project to a Unity Cloud Project using the Services window.

26
Packages/com.unity.services.authentication/Runtime/AuthenticationAsyncOperation.cs


using System;
using System.Collections;
using Unity.Services.Authentication.Utilities;
using Unity.Services.Core;
using Unity.Services.Core.Internal;
using AsyncOperation = Unity.Services.Core.Internal.AsyncOperation;
using Logger = Unity.Services.Authentication.Utilities.Logger;
ILogger m_Logger;
public AuthenticationAsyncOperation(ILogger logger)
public AuthenticationAsyncOperation()
m_Logger = logger;
m_AsyncOperation = new AsyncOperation();
m_AsyncOperation.SetInProgress();
}

{
m_AuthenticationException = new AuthenticationException(AuthenticationError.UnknownError, null, innerException);
}
LogAuthenticationException(m_AuthenticationException);
Logger.LogException(m_AuthenticationException);
BeforeFail?.Invoke(this);
m_AsyncOperation.Fail(m_AuthenticationException);

/// <inheritdoc/>
object IEnumerator.Current => null;
void LogAuthenticationException(AuthenticationException exception)
{
if (m_Logger == null)
{
return;
}
var logMessage = exception.Message;
if (exception.InnerException != null)
{
logMessage += $" cause: ${exception.InnerException}";
}
m_Logger.Error(logMessage);
}
}
}

49
Packages/com.unity.services.authentication/Runtime/AuthenticationNetworkClient.cs


using System.Text;
using Unity.Services.Authentication.Models;
using Unity.Services.Authentication.Utilities;
using Unity.Services.Core.Environments.Internal;
using Logger = Unity.Services.Authentication.Utilities.Logger;
namespace Unity.Services.Authentication
{

readonly INetworkingUtilities m_NetworkClient;
readonly ICodeChallengeGenerator m_CodeChallengeGenerator;
readonly ILogger m_Logger;
readonly string m_WellKnownUrl;
readonly string m_AnonymousUrl;

string m_OAuthClientId;
string m_SessionChallengeCode;
/// <summary>
/// the environments component in the core registry.
/// this is stored in case there is a reinitialization or a change in environments ever happens during runtime.
/// </summary>
IEnvironments m_EnvironmentComponent;
IEnvironments environment,
INetworkingUtilities networkClient,
ILogger logger)
INetworkingUtilities networkClient)
m_Logger = logger;
m_OAuthClientId = "default";

m_OAuthUrl = authenticationHost + k_OAuthUrlStem;
m_OAuthTokenUrl = authenticationHost + k_OAuthTokenUrlStem;
m_OAuthRevokeTokenUrl = authenticationHost + k_OauthRevokeStem;
m_EnvironmentComponent = environment;
m_CommonHeaders = new Dictionary<string, string>
{

public IWebRequest<SignInResponse> SignInAnonymously()
{
return m_NetworkClient.Post<SignInResponse>(m_AnonymousUrl, m_CommonHeaders);
return m_NetworkClient.Post<SignInResponse>(m_AnonymousUrl, WithEnvironment(GetCommonHeaders()));
}
public IWebRequest<SignInResponse> SignInWithSessionToken(string token)

SessionToken = token
}, m_CommonHeaders);
}, WithEnvironment(GetCommonHeaders()));
return m_NetworkClient.PostJson<SignInResponse>(m_ExternalTokenUrl, externalToken, m_CommonHeaders);
return m_NetworkClient.PostJson<SignInResponse>(m_ExternalTokenUrl, externalToken, WithEnvironment(GetCommonHeaders()));
return m_NetworkClient.PostJson<SignInResponse>(m_LinkExternalTokenUrl, externalToken, WithAccessToken(accessToken));
return m_NetworkClient.PostJson<SignInResponse>(m_LinkExternalTokenUrl, externalToken, WithEnvironment(WithAccessToken(GetCommonHeaders(), accessToken)));
}
public IWebRequest<OAuthAuthCodeResponse> RequestAuthCode(string idToken)

}
catch (Exception ex)
{
m_Logger.Error("Failed to extract auth code. " + ex);
Logger.LogError("Failed to extract auth code. " + ex.Message);
Logger.LogException(ex);
return null;
}
}

string code;
if (!queryParams.TryGetValue("code", out code))
{
m_Logger.Error($"Failed to extract auth code. Query parameter 'code' is not found. Location: {locationUri}");
Logger.LogError($"Failed to extract auth code. Query parameter 'code' is not found. Location: {locationUri}");
}
return code;

return authCodeRequest.ResponseBody.AccessToken;
}
Dictionary<string, string> WithAccessToken(string accessToken)
Dictionary<string, string> WithAccessToken(Dictionary<string, string> headers, string accessToken)
return new Dictionary<string, string>(m_CommonHeaders) { ["Authorization"] = "Bearer " + accessToken };
headers["Authorization"] = "Bearer " + accessToken;
return headers;
}
Dictionary<string, string> WithEnvironment(Dictionary<string, string> headers)
{
var env = m_EnvironmentComponent.Current;
if (!string.IsNullOrEmpty(env))
{
headers["UnityEnvironment"] = m_EnvironmentComponent.Current;
}
return headers;
}
Dictionary<string, string> GetCommonHeaders()
{
return new Dictionary<string, string>(m_CommonHeaders);
}
}
}

10
Packages/com.unity.services.authentication/Runtime/AuthenticationService.cs


using System;
using Unity.Services.Authentication.Utilities;
using Logger = Unity.Services.Authentication.Utilities.Logger;
public class AuthenticationService
/// <summary>
/// The entry class to the Authentication Service.
/// </summary>
public static class AuthenticationService
/// <summary>
/// The default singleton instance to access authentication service.
/// </summary>
public static IAuthenticationService Instance { get; internal set; }
}
}

53
Packages/com.unity.services.authentication/Runtime/AuthenticationServiceInternal.cs


using System;
using System.Runtime.CompilerServices;
using Unity.Services.Core;
[assembly: InternalsVisibleTo("Unity.Services.Authentication.Tests")]
[assembly: InternalsVisibleTo("Unity.Services.Authentication.EditorTests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] // For Moq
using Unity.Services.Core.Internal;
namespace Unity.Services.Authentication
{

readonly ICache m_Cache;
readonly IScheduler m_Scheduler;
readonly IDateTimeWrapper m_DateTime;
readonly ILogger m_Logger;
IWebRequest<SignInResponse> m_DelayedTokenRequest;
string m_PlayerId;

IJwtDecoder jwtDecoder,
ICache cache,
IScheduler scheduler,
IDateTimeWrapper dateTime,
ILogger logger)
IDateTimeWrapper dateTime)
{
m_NetworkClient = networkClient;
m_JwtDecoder = jwtDecoder;

m_Logger = logger;
State = AuthenticationState.SignedOut;
}

{
if (attempt < k_WellKnownKeysMaxAttempt)
{
m_Logger.Warning($"Well-known keys request failed (attempt: {attempt}): {response.ResponseCode}, {response.ErrorMessage}");
Logger.LogWarning($"Well-known keys request failed (attempt: {attempt}): {response.ResponseCode}, {response.ErrorMessage}");
GetWellKnownKeys(asyncOperation, attempt + 1);
}
else

return;
}
m_Logger.Info("Well-known keys have arrived!");
Logger.LogVerbose("Well-known keys have arrived!");
WellKnownKeys = response.ResponseBody;
if (State == AuthenticationState.VerifyingAccessToken)

internal IAsyncOperation LinkWithExternalToken(ExternalTokenRequest externalToken)
{
var operation = new AuthenticationAsyncOperation(m_Logger);
var operation = new AuthenticationAsyncOperation();
if (IsAuthorized)
{
var linkResult = m_NetworkClient.LinkWithExternalToken(AccessToken, externalToken);

{
m_Logger.Warning("The player is not authorized. Wait until authorized before attempting to link.");
Logger.LogWarning("The player is not authorized. Wait until authorized before attempting to link.");
operation.Fail(AuthenticationError.ClientInvalidUserState);
}

return SessionTokenNotExistsError();
}
m_Logger.Info("Continuing existing session with cached token.");
Logger.LogVerbose("Continuing existing session with cached token.");
return StartSigningIn(m_NetworkClient.SignInWithSessionToken(sessionToken), isRefreshRequest);
}

if (WellKnownKeys == null)
{
m_Logger.Info("Well-known keys have not arrived yet, waiting on them to complete sign-in.");
Logger.LogVerbose("Well-known keys have not arrived yet, waiting on them to complete sign-in.");
m_DelayedTokenRequest = request;

{
if (IsSignedIn)
{
m_Logger.Info("Making token refresh request...");
Logger.LogVerbose("Making token refresh request...");
if (State != AuthenticationState.Expired)
{

{
if (request.RequestFailed)
{
m_Logger.Error($"Request failed: {request.ResponseCode}, {request.ErrorMessage}");
Logger.LogError($"Request failed: {request.ResponseCode}, {request.ErrorMessage}");
// NOTE: depending on how long it took to fail, this might occur before the access token has _actually_ expired.
// This is likely safer than risking an expired access token reaching a consuming service.

m_Logger.Warning("Failed to refresh access token due to server error, signing out.");
Logger.LogWarning("Failed to refresh access token due to server error, signing out.");
m_Logger.Warning("Failed to refresh access token due to network error or internal server error, will retry later.");
Logger.LogWarning("Failed to refresh access token due to network error or internal server error, will retry later.");
m_Scheduler.ScheduleAction(RefreshAccessToken, k_ExpiredRefreshAttemptFrequency);

}
else
{
var asyncOp = new AuthenticationAsyncOperation(m_Logger);
var asyncOp = new AuthenticationAsyncOperation();
m_Logger.Info("Refresh complete!");
Logger.LogVerbose("Refresh complete!");
m_Logger.Warning("The access token is not valid. Retry JWKS and refresh again.");
Logger.LogWarning("The access token is not valid. Retry JWKS and refresh again.");
// Refresh failed since we received a bad token. Retry.
m_Scheduler.ScheduleAction(RefreshAccessToken, k_ExpiredRefreshAttemptFrequency);

if (IsAuthorized &&
m_DateTime.UtcNow > m_AccessTokenExpiryTime)
{
m_Logger.Info("Application unpause found the access token to have expired already.");
Logger.LogVerbose("Application unpause found the access token to have expired already.");
Expire();
RefreshAccessToken();
}

// NOTE: always call this at the end of a method where state is changed, so that any consumer
// that has subscribed to the event will get the correct data for the new state.
m_Logger.Info($"Moved from state [{State}] to [{newState}]");
Logger.LogVerbose($"Moved from state [{State}] to [{newState}]");
var oldState = State;
State = newState;

var exception = new AuthenticationException(
AuthenticationError.ClientInvalidUserState,
"The player is already signed in. Sign out before attempting to sign in again.");
m_Logger.Warning(exception.Message);
var asyncOp = new AuthenticationAsyncOperation(null);
var asyncOp = new AuthenticationAsyncOperation();
asyncOp.Fail(exception);
return asyncOp;
}

var exception = new AuthenticationException(
AuthenticationError.ClientNoActiveSession,
"There is no cached session token.");
m_Logger.Warning(exception.Message);
var asyncOp = new AuthenticationAsyncOperation(null);
var asyncOp = new AuthenticationAsyncOperation();
asyncOp.Fail(exception);
return asyncOp;
}

return false;
}
m_Logger.Error($"Request failed: {request.ResponseCode}, {request.ErrorMessage}");
Logger.LogError($"Request failed: {request.ResponseCode}, {request.ErrorMessage}");
if (request.NetworkError)
{

/// </summary>
internal AuthenticationAsyncOperation CreateSignInAsyncOperation()
{
var asyncOp = new AuthenticationAsyncOperation(m_Logger);
var asyncOp = new AuthenticationAsyncOperation();
asyncOp.BeforeFail += SendSignInFailedEvent;
return asyncOp;

2
Packages/com.unity.services.authentication/Runtime/Core/AccessTokenComponent.cs


using System;
using Unity.Services.Authentication.Internal;
namespace Unity.Services.Authentication
{

20
Packages/com.unity.services.authentication/Runtime/Core/AuthenticationPackageInitializer.cs


using System;
using Unity.Services.Authentication.Internal;
using Unity.Services.Core;
using Unity.Services.Core.Internal;
using Unity.Services.Core.Environments.Internal;
using Logger = Unity.Services.Authentication.Utilities.Logger;
namespace Unity.Services.Authentication
{

public Task Initialize(CoreRegistry registry)
{
var logger = new Logger("[Authentication]");
var networkUtilities = new NetworkingUtilities(Scheduler.Instance, logger);
var networkUtilities = new NetworkingUtilities(Scheduler.Instance);
registry.GetServiceComponent<IEnvironments>(),
networkUtilities,
logger);
networkUtilities);
new JwtDecoder(dateTime, logger),
new JwtDecoder(dateTime),
dateTime,
logger);
dateTime);
AuthenticationService.Instance = authenticationService;
registry.RegisterServiceComponent<IPlayerId>(new PlayerIdComponent(authenticationService));

static void Register()
{
CoreRegistry.Instance.RegisterPackage(new AuthenticationPackageInitializer())
.DependsOn<IEnvironments>()
.ProvidesComponent<IPlayerId>()
.ProvidesComponent<IAccessToken>();
}

1
Packages/com.unity.services.authentication/Runtime/Core/PlayerIdComponent.cs


using System;
using Unity.Services.Authentication.Internal;
namespace Unity.Services.Authentication
{

100
Packages/com.unity.services.authentication/Runtime/IAuthenticationService.cs


namespace Unity.Services.Authentication
{
/// <summary>
/// The functions for Authentication service.
/// </summary>
/// <summary>
/// Whether the player is signed in or not.
/// </summary>
/// <summary>
/// Returns the access token if the current player is signed in, otherwise null.
/// </summary>
/// <summary>
/// Returns the player's ID if the current player is signed in, otherwise null.
/// </summary>
/// <summary>
/// Invoked when a sign-in attempt has completed successfully.
/// </summary>
/// <summary>
/// Invoked when a sign-out attempt has completed successfully.
/// </summary>
/// <summary>
/// Invoked when a sign-in attempt has failed, giving the error as the
/// <see cref="AuthenticationException"/> parameter.
/// </summary>
/// <summary>
/// Sign the player in anonymously. No credentials are required and the session is confined to the current device.
/// </summary>
/// <remarks>
/// If player has already signed in previously with a session token stored on the device, it signs the player back in no matter whether it's an anonymous player or not.
/// </remarks>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Sign the player in with the session token stored on the device.
/// </summary>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Sign in using Apple's ID token.
/// </summary>
/// <param name="idToken">Apple's ID token</param>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Link the current player with Apple account using Apple's ID token.
/// </summary>
/// <param name="idToken">Apple's ID token</param>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Sign in using Google's ID token.
/// </summary>
/// <param name="idToken">Google's ID token</param>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Link the current player with Google account using Google's ID token.
/// </summary>
/// <param name="idToken">Google's ID token</param>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Sign in using Facebook's access token.
/// </summary>
/// <param name="accessToken">Facebook's access token</param>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Link the current player with Facebook account using Facebook's access token.
/// </summary>
/// <param name="accessToken">Facebook's access token</param>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Sign in using Steam's session ticket.
/// </summary>
/// <param name="sessionTicket">Steam's session ticket</param>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Link the current player with Steam account using Steam's session ticket.
/// </summary>
/// <param name="sessionTicket">Steam's session ticket</param>
/// <returns>Task for the async operation</returns>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// Sign the current player out.
/// </summary>
/// <exception cref="AuthenticationException">An exception containing the message and ErrorCode of the error. Refer to <see cref="AuthenticationError"/> for error codes.</exception>
/// <summary>
/// The function to call when application is unpaused.
/// It triggers and access token refresh if needed.
/// </summary>
void ApplicationUnpaused();
}
}

14
Packages/com.unity.services.authentication/Runtime/JwtDecoder.cs


static readonly char[] k_JwtSeparator = { '.' };
readonly IDateTimeWrapper m_DateTime;
readonly ILogger m_Logger;
internal JwtDecoder(IDateTimeWrapper dateTime, ILogger logger)
internal JwtDecoder(IDateTimeWrapper dateTime)
m_Logger = logger;
}
public T Decode<T>(string token, WellKnownKeys keys) where T : BaseJwt

var secondsSinceEpoch = m_DateTime.SecondsSinceUnixEpoch();
if (secondsSinceEpoch >= payloadData.ExpirationTimeUnix)
{
m_Logger.Error("Token has expired.");
Logger.LogError("Token has expired.");
return null;
}

return payloadData;
}
m_Logger.Error("Token signature could not be verified.");
Logger.LogError("Token signature could not be verified.");
m_Logger.Error($"That is not a valid token (expected 3 parts but has {parts.Length}).");
Logger.LogError($"That is not a valid token (expected 3 parts but has {parts.Length}).");
return null;
}

var verified = Verify(header, payload, signature, Base64UrlDecode(key.N), Base64UrlDecode(key.E));
if (!verified)
{
m_Logger.Error("Signature failed verification!");
Logger.LogError("Signature failed verification!");
m_Logger.Error("Unable to verify signature, does not use a well-known key ID.");
Logger.LogError("Unable to verify signature, does not use a well-known key ID.");
return false;
}

15
Packages/com.unity.services.authentication/Runtime/Unity.Services.Authentication.api


public AuthenticationException(string errorCode, string message, System.Exception innerException) {}
}
public class AuthenticationService
public static class AuthenticationService
public AuthenticationService() {}
}
public interface IAuthenticationService

public abstract void SignOut();
}
}
namespace Unity.Services.Authentication.Utilities
{
public enum LogLevel
{
public const Unity.Services.Authentication.Utilities.LogLevel ErrorsOnly = 1;
public const Unity.Services.Authentication.Utilities.LogLevel Off = 0;
public int value__;
public const Unity.Services.Authentication.Utilities.LogLevel Verbose = 3;
public const Unity.Services.Authentication.Utilities.LogLevel WarningsAndErrors = 2;
}
}

3
Packages/com.unity.services.authentication/Runtime/Unity.Services.Authentication.asmdef


"name": "Unity.Services.Authentication",
"references": [
"Unity.Services.Core",
"Unity.Services.Core.Internal"
"Unity.Services.Core.Internal",
"Unity.Services.Core.Environments"
],
"includePlatforms": [],
"excludePlatforms": [],

164
Packages/com.unity.services.authentication/Runtime/Utilities/Logger.cs


using System;
using System.Text;
using System.Diagnostics;
using Debug = UnityEngine.Debug;
/// <summary>
/// LogLevel is used to control the logs that are written to Unity for debugging.
/// </summary>
public enum LogLevel
{
/// <summary>
/// Disable all logs from Authentication SDK.
/// </summary>
Off = 0,
/// <summary>
/// Show errors in Authentication SDK.
/// </summary>
ErrorsOnly = 1,
/// <summary>
/// Show warnings and errors in Authentication SDK.
/// </summary>
WarningsAndErrors = 2,
/// <summary>
/// Show all logs in Authentication SDK.
/// </summary>
Verbose = 3
}
interface ILogger
{
void Info(string message);
void Warning(string message);
void Error(string message);
void Info(string format, params object[] args);
void Warning(string format, params object[] args);
void Error(string format, params object[] args);
}
class Logger : ILogger
static class Logger
readonly string m_Prefix;
delegate void LogMethod(object message);
public LogLevel LogLevel { get; private set; }
public Logger(string prefix, LogLevel logLevel = LogLevel.ErrorsOnly)
{
m_Prefix = prefix;
LogLevel = logLevel;
}
public void SetLogLevel(LogLevel level)
{
LogLevel = level;
}
public void Info(string message)
{
if (LogLevel >= LogLevel.Verbose)
{
Log(Debug.Log, message);
}
}
public void Info(string format, params object[] args)
{
if (LogLevel >= LogLevel.Verbose)
{
Log(Debug.Log, format, args);
}
}
public void Warning(string message)
{
if (LogLevel >= LogLevel.WarningsAndErrors)
{
Log(Debug.LogWarning, message);
}
}
const string k_Tag = "[Authentication]";
public void Warning(string format, params object[] args)
{
if (LogLevel >= LogLevel.WarningsAndErrors)
{
Log(Debug.LogWarning, format, args);
}
}
public void Error(string message)
{
if (LogLevel >= LogLevel.ErrorsOnly)
{
Log(Debug.LogError, message);
}
}
public void Error(string format, params object[] args)
{
if (LogLevel >= LogLevel.ErrorsOnly)
{
Log(Debug.LogError, format, args);
}
}
void Log(LogMethod log, string format, params object[] args)
{
try
{
var sb = new StringBuilder();
sb.Append(m_Prefix);
sb.Append(" ");
if (args?.Length == 0)
{
// There is no args, so it's supposed to be a raw string to log.
// Don't do AppendFormat since it will throw FormatException if the format string contains
// placeholder character {}.
sb.Append(format);
}
else
{
sb.AppendFormat(format, args);
}
const string k_VerboseLoggingDefine = "ENABLE_UNITY_AUTHENTICATION_VERBOSE_LOGGING";
log(sb.ToString());
}
catch (Exception e)
{
try
{
// It's possible to get FormatException if the format string doesn't match args.
// Fallback to a non-formatted string
public static void Log(object message) => Debug.unityLogger.Log(k_Tag, message);
public static void LogWarning(object message) => Debug.unityLogger.LogWarning(k_Tag, message);
public static void LogError(object message) => Debug.unityLogger.LogError(k_Tag, message);
public static void LogException(Exception exception) => Debug.unityLogger.Log(LogType.Exception, k_Tag, exception);
var sb = new StringBuilder();
sb.Append(m_Prefix);
sb.Append(" [");
sb.Append(e.Message);
sb.Append("] ");
sb.Append(format);
foreach (var arg in args)
{
sb.Append(" ");
sb.Append(arg);
}
[Conditional("UNITY_ASSERTIONS")]
public static void LogAssertion(object message) => Debug.unityLogger.Log(LogType.Assert, k_Tag, message);
log(sb.ToString());
}
catch
{
// Ignore the exception if it fails again, best effort.
// It's possible that log() itself throws exception, then there isn't a good way to write a log.
}
}
}
#if !ENABLE_UNITY_SERVICES_VERBOSE_LOGGING
[Conditional(k_VerboseLoggingDefine)]
#endif
public static void LogVerbose(object message) => Debug.unityLogger.Log(k_Tag, message);
}
}

14
Packages/com.unity.services.authentication/Runtime/Utilities/Logger.cs.meta


fileFormatVersion: 2
guid: b00545242abac4441933a4ae8ff83a03
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: e6375e7dc6e94704ae9cf19989f51c02
timeCreated: 1623256583

11
Packages/com.unity.services.authentication/Runtime/Utilities/NetworkingUtilities.cs


using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Newtonsoft.Json;
using UnityEngine;
[assembly: InternalsVisibleTo("Unity.Services.Authentication.Editor")]
[assembly: InternalsVisibleTo("Unity.Services.Utilities.Tests")]

class NetworkingUtilities : INetworkingUtilities
{
readonly IScheduler m_Scheduler;
readonly ILogger m_Logger;
public NetworkingUtilities(IScheduler scheduler, ILogger logger)
public NetworkingUtilities(IScheduler scheduler)
m_Logger = logger;
}
/// <summary>

public IWebRequest<T> Get<T>(string url, IDictionary<string, string> headers = null, int maximumAttempts = 1)
{
var request = new WebRequest<T>(m_Scheduler,
m_Logger,
WebRequestVerb.Get,
url,
headers,

public IWebRequest<T> Post<T>(string url, IDictionary<string, string> headers = null, int maximumAttempts = 1)
{
var request = new WebRequest<T>(m_Scheduler,
m_Logger,
WebRequestVerb.Post,
url,
headers,

var jsonPayload = JsonConvert.SerializeObject(payload);
var request = new WebRequest<T>(m_Scheduler,
m_Logger,
WebRequestVerb.Post,
url,
headers,

public IWebRequest<T> PostForm<T>(string url, string payload, IDictionary<string, string> headers = null, int maximumAttempts = 1)
{
var request = new WebRequest<T>(m_Scheduler,
m_Logger,
WebRequestVerb.Post,
url,
headers,

var jsonPayload = JsonConvert.SerializeObject(payload);
var request = new WebRequest<T>(m_Scheduler,
m_Logger,
WebRequestVerb.Put,
url,
headers,

public IWebRequest<T> Delete<T>(string url, IDictionary<string, string> headers = null, int maximumAttempts = 1)
{
var request = new WebRequest<T>(m_Scheduler,
m_Logger,
WebRequestVerb.Delete,
url,
headers,

34
Packages/com.unity.services.authentication/Runtime/Utilities/WebRequest.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using UnityEngine;

const int k_RetryBackoffSeconds = 10;
readonly IScheduler m_Scheduler;
readonly ILogger m_Logger;
readonly WebRequestVerb m_Verb;
readonly string m_Url;
readonly IDictionary<string, string> m_Headers;

internal int RequestTimeout { get; set; }
internal WebRequest(IScheduler scheduler,
ILogger logger,
WebRequestVerb verb,
string url,
IDictionary<string, string> headers,

int attempts)
{
m_Scheduler = scheduler;
m_Logger = logger;
m_Verb = verb;
m_Url = url;
m_Headers = headers;

internal void Send()
{
Logger.LogVerbose($"[WebRequest] {m_Verb.ToString().ToUpper()} {m_Url}\n" +
$"{string.Join("\n", m_Headers?.Select(x => x.Key + ": " + x.Value) ?? new string[]{})}\n" +
(m_Payload ?? ""));
UnityWebRequest unityWebRequest;
switch (m_Verb)
{

case WebRequestVerb.Put:
if (string.IsNullOrEmpty(m_Payload))
{
unityWebRequest = UnityWebRequest.Put(m_Url, string.Empty);
// UnityWebRequest doesn't allow empty put request body.
throw new ArgumentException("PUT payload cannot be empty.");
}
else
{

break;
case WebRequestVerb.Delete:
unityWebRequest = UnityWebRequest.Delete(m_Url);
unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
unityWebRequest = UnityWebRequest.Get(m_Url);
break;
throw new ArgumentException("Unknown verb " + m_Verb);
}
if (m_Headers != null)

unityWebRequest.error,
unityWebRequest.downloadHandler?.text,
unityWebRequest.GetResponseHeaders());
unityWebRequest.Dispose();
}
internal void RequestCompleted(long responseCode,

string bodyText,
IDictionary<string, string> headers)
{
Logger.LogVerbose($"[WebResponse] {m_Verb.ToString().ToUpper()} {m_Url}\n" +
$"{string.Join("\n", headers?.Select(x => x.Key + ": " + x.Value) ?? new string[]{})}\n" +
$"{bodyText}\n{errorText}\n");
if (hasNetworkError && m_Attempts > 0)
if (hasNetworkError && m_Scheduler != null && m_Attempts > 0)
m_Logger.Warning("Network error detected, retrying...");
Logger.LogWarning("Network error detected, retrying...");
m_Scheduler.ScheduleAction(Send, k_RetryBackoffSeconds);
}

ErrorMessage = errorText;
}
m_Logger.Warning("Request completed with error: {0}", ErrorMessage);
Logger.LogWarning($"Request completed with error: {ErrorMessage}");
}
else
{

if (string.IsNullOrEmpty(bodyText))
{
m_Logger.Info("Request completed successfully!");
Logger.LogVerbose("Request completed successfully!");
}
else
{

m_Logger.Info("Request completed successfully!");
Logger.LogVerbose("Request completed successfully!");
m_Logger.Warning("Failed to deserialize object!" + ex.Message);
Logger.LogError("Failed to deserialize object! " + ex.Message);
Logger.LogException(ex);
ErrorMessage = ex.Message;
RequestFailed = true;
}

10
Packages/com.unity.services.authentication/package.json


{
"name": "com.unity.services.authentication",
"displayName": "Unity Authentication SDK",
"version": "0.5.0-preview",
"version": "0.7.1-preview",
"com.unity.services.core": "1.1.0-pre.2",
"com.unity.services.core": "1.1.0-pre.4",
"com.unity.services.authentication.tests": "0.5.0-preview"
"com.unity.services.authentication.tests": "0.7.1-preview"
"footprint": "d6dbb1efb74d58081d3f1b2ba4e0de24ebd466c4"
"footprint": "39b7ab526678124522acde1e9ef41ad4d2ce8c4a"
"revision": "724ce4a71dab198ef36654f093af01b116d1c641"
"revision": "0924832b7ba1efb195eeff4318693daefb886f24"
}
}

27
Packages/com.unity.services.core/CHANGELOG.md


The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.1.0-pre.4] - 2021-07-21
### Changed
- [Breaking Change] Move all classes meant for internal use to `*.Internal` namespace.
## [1.1.0-pre.3] - 2021-07-15
### Added
- `SetEnvironmentName` Initialization option to set the environment services should use.
- MiniJson.
### Removed
- Newtonsoft dependency.
## [1.1.0-pre.2] - 2021-06-14
### Added
- `IProjectConfiguration` component to access services settings at runtime.

- Installation Identifier component.
- Service Activation popup.
### Changed
### Changed
- Members:
- Members:
- Members:
- Members:
- `ServiceFlagName` to `FlagName`
- `IOperateServiceEnabler` to `IEditorGameServiceEnabler`
- `OperateServiceRegistry` to `EditorGameServiceRegistry`

- Methods:
- Methods:
- Members:
- Members:
- GlobalDefine:
- GlobalDefine:
## [0.2.0-preview] - 2021-04-14
### Added

6
Packages/com.unity.services.core/Editor/Core/BackendHelpers/JsonHelper.cs


using System;
using Newtonsoft.Json;
using UnityEngine;
namespace Unity.Services.Core.Editor
{

{
if (!string.IsNullOrEmpty((json)))
if (!string.IsNullOrEmpty(json))
dest = JsonConvert.DeserializeObject<T>(json);
dest = JsonUtility.FromJson<T>(json);
return true;
}
catch (Exception)

26
Packages/com.unity.services.core/Editor/Core/BackendHelpers/UnityWebRequestHelper.cs


{
static class UnityWebRequestHelper
{
internal static bool IsUnityWebRequestReadyForTextExtract(UnityWebRequest unityWebRequest, out string downloadHandlerText)
{
internal static bool IsUnityWebRequestReadyForTextExtract(UnityWebRequest unityWebRequest, out string downloadHandlerText)
{
var result = unityWebRequest != null && unityWebRequest.result == UnityWebRequest.Result.Success;
var result = unityWebRequest != null && unityWebRequest.result == UnityWebRequest.Result.Success;
var result = unityWebRequest != null &&
!unityWebRequest.isHttpError &&
!unityWebRequest.isNetworkError;
var result = unityWebRequest != null &&
!unityWebRequest.isHttpError &&
!unityWebRequest.isNetworkError;
if (result)
{
downloadHandlerText = unityWebRequest.downloadHandler?.text;
return !string.IsNullOrEmpty(downloadHandlerText);
}
downloadHandlerText = null;
return false;
if (result)
{
downloadHandlerText = unityWebRequest.downloadHandler?.text;
return !string.IsNullOrEmpty(downloadHandlerText);
downloadHandlerText = null;
return false;
}
}
}

33
Packages/com.unity.services.core/Editor/Core/Configuration/ProjectConfigurationBuilder.cs


using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
IPostprocessBuildWithReport,
IDisposable
IPostprocessBuildWithReport
{
static ProjectConfigurationBuilder s_EditorInstance;

public ProjectConfigurationBuilder(IEnumerable<IConfigurationProvider> orderedConfigProviders)
{
m_OrderedConfigProviders = orderedConfigProviders;
}
~ProjectConfigurationBuilder()
{
RemoveConfigFromProject();
}
[InitializeOnLoadMethod]

static void SetUpPlayModeConfigOnEnteringPlayMode(EnterPlayModeOptions _)
{
CreateEditorInstanceIfNone();
ConfigurationUtils.ConfigurationLoader = new EditorConfigurationLoader
ConfigurationUtils.ConfigurationLoader = new MemoryConfigurationLoader
PlayModeConfig = s_EditorInstance.BuildConfiguration()
Config = s_EditorInstance.BuildConfiguration()
};
}

public static void RemoveConfigFromProject()
{
AssetDatabase.DeleteAsset(ConfigurationUtils.ConfigAssetPath);
IoUtils.TryDeleteAssetFile(ConfigurationUtils.RuntimeConfigFullPath);
}
int IOrderedCallback.callbackOrder { get; }

}
GenerateConfigFileInProject();
}
EditorApplication.update += RemoveConfigFromProjectWhenBuildEnds;
void IPostprocessBuildWithReport.OnPostprocessBuild(BuildReport report)
{
RemoveConfigFromProject();
void RemoveConfigFromProjectWhenBuildEnds()
{
if (BuildPipeline.isBuildingPlayer)
{
return;
}
EditorApplication.update -= RemoveConfigFromProjectWhenBuildEnds;
RemoveConfigFromProject();
}
void IDisposable.Dispose()
void IPostprocessBuildWithReport.OnPostprocessBuild(BuildReport report)
{
RemoveConfigFromProject();
}

3
Packages/com.unity.services.core/Editor/Core/Configuration/Unity.Services.Core.Configuration.Editor.asmdef


"name": "Unity.Services.Core.Configuration.Editor",
"references": [
"Unity.Services.Core",
"Unity.Services.Core.Configuration"
"Unity.Services.Core.Configuration",
"Unity.Services.Core.Internal"
],
"includePlatforms": [
"Editor"

12
Packages/com.unity.services.core/Editor/Core/EditorGameService/DefaultCdnConfiguredEndpoint.cs


using Newtonsoft.Json;
using System;
using System.Diagnostics.CodeAnalysis;
using UnityEngine;
[Serializable]
[SuppressMessage("ReSharper", "InconsistentNaming")]
[JsonProperty("core")]
public string Core { get; set; }
[SerializeField]
string core;
public string Core => core;
internal string BuildApiUrl()
{

1
Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceDashboardHelper.cs


var formattedUrl = editorGameService.GetFormattedDashboardUrl();
if (Uri.IsWellFormedUriString(formattedUrl, UriKind.Absolute))
{
EditorGameServiceAnalyticsSender.SendProjectSettingsGoToDashboardEvent(editorGameService.Identifier.GetKey());
Application.OpenURL(formattedUrl);
}
else

2
Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceFlagEnabler.cs


using System;
using System.ComponentModel;
using System.Text;
using Unity.Services.Core.Internal;
using UnityEngine;
using UnityEngine.Networking;
namespace Unity.Services.Core.Editor

10
Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceRegistry.cs


using System.Data;
using System.Linq;
using UnityEditor;
using Unity.Services.Core.Internal;
using UnityEngine;
namespace Unity.Services.Core.Editor

}
else
{
Debug.LogError($"Type `{type.FullName}` is not a valid service.");
CoreLogger.LogError($"Type `{type.FullName}` is not a valid service.");
}
}

#endif
}
/// <summary>
/// Destructor of the registry.
/// </summary>
~EditorGameServiceRegistry()
{
StopListeningToProjectStateChanges();

}
/// <summary>
/// Get the instance of a <see cref="IEditorGameService"/> type.
/// Get the instance of a registered <see cref="IEditorGameService"/>.
/// <param name="serviceIdentifier">The identifier for a service</param>
/// <typeparam name="TIdentifier">The type of the identifier for a service</typeparam>
/// <returns>Return the instance of the given <see cref="IEditorGameService"/> type if it has been registered.</returns>
public IEditorGameService GetEditorGameService<TIdentifier>()
where TIdentifier : struct, IEditorGameServiceIdentifier

8
Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceRemoteConfiguration.cs


using System;
using System.Text;
using Unity.Services.Core.Internal;
using Unity.Services.Core.Networking.Internal;
using UnityEngine;
namespace Unity.Services.Core.Editor
{

{
return Encoding.UTF8.GetString(bytes);
}
catch (Exception)
catch (Exception e)
// ignored, String decoding failed, we'll return null
// The exception is ignored; String decoding failed, we'll return null
Debug.LogWarning(e);
}
}

29
Packages/com.unity.services.core/Editor/Core/EditorGameService/EditorGameServiceSettingsProvider.cs


using UnityEditor.Connect;
using UnityEngine;
using UnityEngine.UIElements;
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Editor
{

#if ENABLE_EDITOR_GAME_SERVICES
IProjectEditorDrawerFactory m_ProjectBindDrawerFactory;
IProjectEditorDrawerFactory m_CoppaDrawerFactory;
IUserRoleHandler m_UserRoleHandler;
#endif
/// <summary>

#if ENABLE_EDITOR_GAME_SERVICES
internal EditorGameServiceSettingsProvider(string path, SettingsScope scopes, IProjectEditorDrawerFactory projectBindDrawer,
IProjectEditorDrawerFactory projectCoppaDrawer, IProjectStateRequest projectStateRequest = null, IUserRoleRequest userRoleRequest = null, IEnumerable<string> keywords = null)
IProjectEditorDrawerFactory projectCoppaDrawer, IProjectStateRequest projectStateRequest = null, IUserRoleHandler userRoleHandler = null, IEnumerable<string> keywords = null)
: base(path, scopes, keywords)
{
m_ProjectStateRequest = projectStateRequest ?? new ProjectStateRequest();

m_UserRoleHandler = userRoleHandler ?? EditorGameServiceRegistry.Instance.UserRoleHandler;
activateHandler = ActivateSettingsProvider;
deactivateHandler = DeactivateSettingsProvider;
}

#if ENABLE_EDITOR_GAME_SERVICES
CloudProjectSettingsEventManager.instance.projectStateChanged += OnProjectStateChanged;
EditorGameServiceRegistry.Instance.UserRoleHandler.UserRoleChanged += OnUserRoleChanged;
EditorGameServiceRegistry.Instance.UserRoleHandler.TrySendUserRoleRequest();
m_UserRoleHandler.UserRoleChanged += OnUserRoleChanged;
m_UserRoleHandler.TrySendUserRoleRequest();
#endif
}

CloudProjectSettingsEventManager.instance.projectStateChanged -= OnProjectStateChanged;
EditorGameServiceRegistry.Instance.UserRoleHandler.UserRoleChanged -= OnUserRoleChanged;
m_UserRoleHandler.UserRoleChanged -= OnUserRoleChanged;
if (EditorGameServiceRegistry.Instance.UserRoleHandler.IsBusy())
#if ENABLE_EDITOR_GAME_SERVICES
if (m_UserRoleHandler.IsBusy())
#endif
var projectState = m_ProjectStateRequest.GetProjectState();
if (m_CurrentProjectState.HasDiff(projectState))

void DrawAccessTokenErrorUI(VisualElement parentVisualElement)
{
AccessTokenErrorUiHelper.AddAccessTokenErrorUI(parentVisualElement);
Debug.LogWarning(k_AuthenticationErrorMessage);
CoreLogger.LogWarning(k_AuthenticationErrorMessage);
}
internal static bool IsUserLoggedIn(ProjectState projectState)

return projectState.ProjectBound;
}
static bool IsUserRoleSet()
bool IsUserRoleSet()
return EditorGameServiceRegistry.Instance.UserRoleHandler.CurrentUserRole != UserRole.Unknown;
return m_UserRoleHandler.CurrentUserRole != UserRole.Unknown;
static bool IsUserRoleRequestNotAuthorized()
bool IsUserRoleRequestNotAuthorized()
return EditorGameServiceRegistry.Instance.UserRoleHandler.HasAuthorizationError;
return m_UserRoleHandler.HasAuthorizationError;
}
void DrawUserRoleUI(VisualElement parentVisualElement)

}
parentVisualElement.Add(coppaDrawer.GetVisualElement());
if (!IsUserAllowedToEditCoppaCompliance(EditorGameServiceRegistry.Instance.UserRoleHandler.CurrentUserRole))
if (!IsUserAllowedToEditCoppaCompliance(m_UserRoleHandler.CurrentUserRole))
{
parentVisualElement.Q<VisualElement>(NodeName.CoppaContainer)?.Q<VisualElement>(className: ClassName.EditMode)?.SetEnabled(false);
}

if (EditorGameService?.Enabler != null)
{
var toggleValue = EditorGameService.Enabler.IsEnabled();
var toggleEnabled = IsUserAllowedToEditServiceToggle(EditorGameService, projectState, EditorGameServiceRegistry.Instance.UserRoleHandler.CurrentUserRole);
var toggleEnabled = IsUserAllowedToEditServiceToggle(EditorGameService, projectState, m_UserRoleHandler.CurrentUserRole);
var tooltip = string.Empty;
if (!toggleEnabled)
{

33
Packages/com.unity.services.core/Editor/Core/EditorGameService/ServiceFlagEndpoint.cs


using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Diagnostics.CodeAnalysis;
using UnityEngine;
namespace Unity.Services.Core.Editor

[Serializable]
[SuppressMessage("ReSharper", "InconsistentNaming")]
[JsonProperty("core")]
public string Core { get; set; }
[SerializeField]
string core;
public string Core => core;
string BuildApiUrl()
{

public string BuildPayload(string serviceFlagName, bool status)
{
return JsonConvert.SerializeObject(new ServiceFlagPayload(serviceFlagName, status));
}
const string payloadFieldName = "service_flags";
class ServiceFlagPayload
{
// A Dictionary is used here because both the key and the value must be mutable
// the key is the the service flag name and the value is the status bool
[JsonProperty("service_flags")]
Dictionary<string, bool> m_ServiceFlag;
// A Dictionary is used here because both the key and the value must be mutable.
// The key is the the service flag name and the value is the status bool.
var serviceFlags = new Dictionary<string, bool>
{
[serviceFlagName] = status,
};
public ServiceFlagPayload(string serviceFlagName, bool status)
var payload = new Dictionary<string, object>
m_ServiceFlag = new Dictionary<string, bool> { { serviceFlagName, status } };
}
[payloadFieldName] = serviceFlags,
};
return MiniJson.Serialize(payload);
}
}
}

2
Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/IServiceFlagRequest.cs


using UnityEngine;
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Editor
{

2
Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/IServiceFlags.cs


interface IServiceFlags
{
List<string> GetFlagNames();
bool DoesFlagExist(string flagName);
bool IsFlagActive(string flagName);

6
Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/ProjectStateHelper.cs


namespace Unity.Services.Core.Editor
{
class ProjectStateHelper: IProjectStateHelper
class ProjectStateHelper : IProjectStateHelper
{
public bool IsProjectOnlyPartiallyBound(ProjectState projectState)
{

public bool IsProjectBeingBound(ProjectState? cachedProjectState, ProjectState currentProjectState)
{
return (!cachedProjectState.HasValue
|| !cachedProjectState.Value.ProjectBound)
|| !cachedProjectState.Value.ProjectBound)
&& currentProjectState.ProjectBound;
}

|| cachedProjectState.Value.ProjectBound)
|| cachedProjectState.Value.ProjectBound)
&& !currentProjectState.ProjectBound;
}
}

18
Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/ServiceFlagRequest.cs


using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Editor
{

{
resultAsyncOp.Fail(ex);
}
void QueryProjectFlags(IAsyncOperation<DefaultCdnEndpointConfiguration> configurationRequestTask, AsyncOperation<IServiceFlags> resultAsyncOp)
static void QueryProjectFlags(IAsyncOperation<DefaultCdnEndpointConfiguration> configurationRequestTask, AsyncOperation<IServiceFlags> resultAsyncOp)
{
try
{

}
}
void OnFetchServiceFlagsCompleted(UnityWebRequest getServiceFlagsRequest, AsyncOperation<IServiceFlags> resultAsyncOp)
static void OnFetchServiceFlagsCompleted(UnityWebRequest getServiceFlagsRequest, AsyncOperation<IServiceFlags> resultAsyncOp)
{
try
{

static IServiceFlags ExtractServiceFlagsFromUnityWebRequest(UnityWebRequest unityWebRequest)
{
var flags = new Dictionary<string, object>();
IDictionary<string, object> flags = null;
var jsonEntries = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonContent);
flags = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonEntries[k_ServiceFlagsKey].ToString());
var jsonEntries = (IDictionary<string, object>)MiniJson.Deserialize(jsonContent);
flags = (IDictionary<string, object>)jsonEntries[k_ServiceFlagsKey];
Debug.LogError($"Exception occurred when fetching service flags:\n{ex.Message}");
CoreLogger.LogError($"Exception occurred when fetching service flags:\n{ex.Message}");
flags = new Dictionary<string, object>();
return new ServiceFlags(flags);
}
}

10
Packages/com.unity.services.core/Editor/Core/ProjectStateManagement/ServiceFlags.cs


namespace Unity.Services.Core.Editor
{
class ServiceFlags: IServiceFlags
class ServiceFlags : IServiceFlags
{
Dictionary<string, bool> m_FlagsDictionary;
List<string> m_FlagNames;

{
return m_FlagsDictionary[flagName];
}
public ServiceFlags(Dictionary<string, object> flagsDictionary)
public ServiceFlags(IDictionary<string, object> flagsDictionary)
m_FlagsDictionary = new Dictionary<string, bool>();
m_FlagNames = new List<string>();
var flagCount = flagsDictionary.Count;
m_FlagsDictionary = new Dictionary<string, bool>(flagCount);
m_FlagNames = new List<string>(flagCount);
foreach (var entry in flagsDictionary)
{
m_FlagNames.Add(entry.Key);

2
Packages/com.unity.services.core/Editor/Core/UserRoleManagement/IUserRoleRequest.cs


using System;
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Editor
{

5
Packages/com.unity.services.core/Editor/Core/UserRoleManagement/UserRoleHandler.cs


using System;
using Unity.Services.Core.Internal;
using UnityEngine;
using Unity.Services.Core.Editor;
class UserRoleHandler : IDisposable
class UserRoleHandler : IDisposable, IUserRoleHandler
{
IAsyncOperation<UserRole> m_CurrentUserRoleOperation;

58
Packages/com.unity.services.core/Editor/Core/UserRoleManagement/UserRoleRequest.cs


using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Diagnostics.CodeAnalysis;
using Unity.Services.Core.Internal;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;

{
resultAsyncOp.Fail(ex);
}
return resultAsyncOp;
}

{
throw new RequestNotAuthorizedException();
}
var currentUserRole = UserRole.Unknown;
var userList = ExtractUserListFromUnityWebRequest(getProjectUsersRequest);
if (userList != null)

{
throw new UserListNotFoundException();
}
resultAsyncOp.Succeed(currentUserRole);
}
catch (Exception ex)

return userList;
}
}
return null;
}

return user;
}
}
/// <remarks>
/// Serialized field don't follow naming conventions for interoperability reasons.
/// </remarks>
[Serializable]
[SuppressMessage("ReSharper", "InconsistentNaming")]
[JsonProperty("users")]
public User[] Users { get; set; }
[SerializeField]
User[] users;
public User[] Users => users;
/// <remarks>
/// Serialized field don't follow naming conventions for interoperability reasons.
/// </remarks>
[Serializable]
[SuppressMessage("ReSharper", "InconsistentNaming")]
[JsonProperty("foreign_key")]
public string Id { get; set; }
[SerializeField]
string foreign_key;
[JsonProperty("name")]
public string Name { get; set; }
public string Id => foreign_key;
[SerializeField]
string name;
public string Name => name;
[SerializeField]
string email;
public string Email => email;
[JsonProperty("email")]
public string Email { get; set; }
[SerializeField]
string access_granted_by;
[JsonProperty("access_granted_by")]
public string AccessGrantedBy { get; set; }
public string AccessGrantedBy => access_granted_by;
[JsonProperty("role")]
public string RawRole { get; set; }
[SerializeField]
string role;
if (Enum.TryParse(RawRole, true, out UserRole userRole))
if (Enum.TryParse(role, true, out UserRole userRole))
throw new UnknownUserRoleException();
}
}

class UnknownUserRoleException : Exception {}
}
}

3
Packages/com.unity.services.core/Runtime/Configuration/ConfigurationCollectionHelper.cs


using System;
using System.Collections.Generic;
using System.Globalization;
using Unity.Services.Core.Internal;
using UnityEngine;
namespace Unity.Services.Core.Configuration

{
if (!existingEntry.TrySetValue(entry))
{
Debug.LogWarning(
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." +

3
Packages/com.unity.services.core/Runtime/Configuration/ConfigurationUtils.cs


public const string StreamingAssetsFolder = "StreamingAssets";
public const string StreamingAssetsPath = "Assets/" + StreamingAssetsFolder;
public const string ConfigFileName = "UnityServicesProjectConfiguration.json";
public const string ConfigAssetPath = StreamingAssetsPath + "/" + ConfigFileName;
= new RuntimeConfigurationLoader();
= new StreamingAssetsConfigurationLoader();
}
}

1
Packages/com.unity.services.core/Runtime/Configuration/ProjectConfiguration.cs


using System.Collections.Generic;
using System.Globalization;
using Unity.Services.Core.Configuration.Internal;
namespace Unity.Services.Core.Configuration
{

2
Packages/com.unity.services.core/Runtime/Configuration/Utils/StreamingAssetsUtils.cs


using System.Threading.Tasks;
using UnityEngine;
namespace Unity.Services.Core
namespace Unity.Services.Core.Configuration
{
static class StreamingAssetsUtils
{

2
Packages/com.unity.services.core/Runtime/Configuration/Utils/UnityWebRequestUtils.cs


using System.Threading.Tasks;
using UnityEngine.Networking;
namespace Unity.Services.Core
namespace Unity.Services.Core.Configuration
{
static class UnityWebRequestUtils
{

2
Packages/com.unity.services.core/Runtime/Configuration/StreamingAssetsConfigurationLoader.cs


namespace Unity.Services.Core.Configuration
{
class RuntimeConfigurationLoader : IConfigurationLoader
class StreamingAssetsConfigurationLoader : IConfigurationLoader
{
public async Task<SerializableProjectConfiguration> GetConfigAsync()
{

3
Packages/com.unity.services.core/Runtime/Core.Internal/AssemblyInfo.cs


[assembly: InternalsVisibleTo("Unity.Services.Core.Editor")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Networking")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Registration")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Configuration")]
[assembly: InternalsVisibleTo("Unity.Services.Core.Configuration.Editor")]
// Test assemblies
#if UNITY_INCLUDE_TESTS
[assembly: InternalsVisibleTo("Unity.Services.Core.Tests")]

2
Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperation.cs


using System;
using System.Collections;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Default implementation for <see cref="IAsyncOperation"/>.

2
Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperationAwaiter.cs


using System;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Default implementation for <see cref="IAsyncOperationAwaiter"/>.

2
Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperationBase.cs


using System.Runtime.CompilerServices;
using UnityEngine;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Base class for asynchronous operations.

2
Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperationExtensions.cs


using System;
using System.Threading.Tasks;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Set of utility functions added as extensions to

2
Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/AsyncOperationStatus.cs


namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// All supported status of an <see cref="IAsyncOperation"/>.

2
Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/IAsyncOperation.cs


using System;
using System.Collections;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Contract for an asynchronous operation with no result.

2
Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/IAsyncOperationAwaiter.cs


using System.Runtime.CompilerServices;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Contract for objects allowing to use the <see langword="await"/> keyword on an <see cref="IAsyncOperation"/>.

2
Packages/com.unity.services.core/Runtime/Core.Internal/AsyncOperation/TaskAsyncOperation.cs


using System.Threading.Tasks;
using UnityEngine;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Task-based implementation of IAsyncOperation.

4
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Authentication/IAccessToken.cs


using Unity.Services.Core;
using Unity.Services.Core.Internal;
namespace Unity.Services.Authentication
namespace Unity.Services.Authentication.Internal
{
/// <summary>
/// Contract for objects providing an access token to access remote services.

4
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Authentication/IPlayerId.cs


using System;
using Unity.Services.Core;
using Unity.Services.Core.Internal;
namespace Unity.Services.Authentication
namespace Unity.Services.Authentication.Internal
{
/// <summary>
/// Contract for objects providing information with the player identification (PlayerID) for currently signed in player.

4
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Configuration/IProjectConfiguration.cs


namespace Unity.Services.Core.Configuration
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Configuration.Internal
{
/// <summary>
/// Component for project configuration.

5
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Device/IInstallationId.cs


namespace Unity.Services.Core.Device
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Device.Internal
{
/// <summary>
/// Component providing a Unity Installation Identifier

/// <summary>
/// Returns Unity Installation Identifier
/// </summary>
/// <returns>The Installation Identifier</returns>
string GetOrCreateIdentifier();
}
}

4
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Environments/IEnvironments.cs


namespace Unity.Services.Core.Environments
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Environments.Internal
{
/// <summary>
/// Component providing the Unity Service Environment

2
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/HttpOptions.cs


namespace Unity.Services.Core.Networking
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Contract for objects containing all settings to customize the behaviour of a HTTP request sending.

2
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/HttpRequest.cs


using System.Collections.Generic;
namespace Unity.Services.Core.Networking
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Contain all data of an HTTP request.

2
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/HttpRequestExtensions.cs


namespace Unity.Services.Core.Networking
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Utility extensions on <see cref="HttpRequest"/>.

2
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/HttpResponse.cs


using System.Collections.Generic;
namespace Unity.Services.Core.Networking
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Contain all data from a server response to a <see cref="HttpRequest"/>.

4
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/IHttpClient.cs


namespace Unity.Services.Core.Networking
using Unity.Services.Core.Internal;
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Contract for objects able to send an HTTP request.

2
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/ReadOnlyHttpRequest.cs


using System.Collections.Generic;
namespace Unity.Services.Core.Networking
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Read-only handle to a <see cref="HttpRequest"/>.

2
Packages/com.unity.services.core/Runtime/Core.Internal/Components/Networking/ReadOnlyHttpResponse.cs


using System.Collections.Generic;
namespace Unity.Services.Core.Networking
namespace Unity.Services.Core.Networking.Internal
{
/// <summary>
/// Read-only handle to a <see cref="HttpResponse"/>.

2
Packages/com.unity.services.core/Runtime/Core.Internal/Registry/CircularDependencyException.cs


namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Exception to use two registered <see cref="IInitializablePackage"/> depend on the other.

14
Packages/com.unity.services.core/Runtime/Core.Internal/Registry/CoreRegistration.cs


namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
/// Provides a fluent interface to define its dependencies and provided components and services.
/// Provides a fluent interface to define its components dependencies and provisions.
/// The registry to register additional dependencies and provisions.
/// The registry containing dependencies and provisions.
readonly CoreRegistry m_Registry;
readonly IPackageRegistry m_Registry;
/// <summary>
/// The hash of the type of the handled <see cref="IInitializablePackage"/>.

internal CoreRegistration(CoreRegistry registry, int packageHash)
internal CoreRegistration(IPackageRegistry registry, int packageHash)
m_PackageHash = packageHash;
}

where T : IServiceComponent
{
m_Registry.RegisterDependency<T>(m_PackageHash);
return this;
}

where T : IServiceComponent
{
m_Registry.RegisterOptionalDependency<T>(m_PackageHash);
return this;
}

where T : IServiceComponent
{
m_Registry.RegisterProvision<T>(m_PackageHash);
return this;
}
}

169
Packages/com.unity.services.core/Runtime/Core.Internal/Registry/CoreRegistry.cs


using System;
using Unity.Services.Core.Internal;
using NotNull = JetBrains.Annotations.NotNullAttribute;
using SuppressMessage = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// A container to store all available <see cref="IInitializablePackage"/>

{
const string k_LockedPackageRegistrationErrorMessage = "Package registration has been blocked. " +
"Make sure to register service packages in" +
"[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)].";
const string k_LockedComponentRegistrationErrorMessage = "Component registration has been blocked. " +
"Make sure to register service components before all packages have finished initializing.";
/// <summary>
/// Key: Hash code of a <see cref="IServiceComponent"/> type.
/// Value: Component instance.
/// </summary>
internal readonly Dictionary<int, IServiceComponent> ComponentTypeHashToInstance;
[NotNull]
internal IPackageRegistry PackageRegistry { get; private set; }
internal DependencyTree Tree;
internal bool IsPackageRegistrationLocked { get; private set; }
internal bool IsComponentRegistrationLocked { get; private set; }
[NotNull]
internal IComponentRegistry ComponentRegistry { get; private set; }
: this(new DependencyTree()) {}
{
var dependencyTree = new DependencyTree();
PackageRegistry = new PackageRegistry(dependencyTree);
ComponentRegistry = new ComponentRegistry(dependencyTree.ComponentTypeHashToInstance);
}
internal CoreRegistry(DependencyTree tree)
internal CoreRegistry(
[NotNull] IPackageRegistry packageRegistry,
[NotNull] IComponentRegistry componentRegistry)
Tree = tree;
ComponentTypeHashToInstance = tree.ComponentTypeHashToInstance;
PackageRegistry = packageRegistry;
ComponentRegistry = componentRegistry;
}
/// <summary>

/// The service package instance to register.
/// </param>
/// <typeparam name="T">
/// <typeparam name="TPackage">
/// The type of <see cref="IInitializablePackage"/> to register.
/// </typeparam>
/// <returns>

public CoreRegistration RegisterPackage<T>(T package)
where T : IInitializablePackage
public CoreRegistration RegisterPackage<TPackage>(
[NotNull] TPackage package)
where TPackage : IInitializablePackage
if (IsPackageRegistrationLocked)
{
throw new InvalidOperationException(k_LockedPackageRegistrationErrorMessage);
}
var packageTypeHash = typeof(T).GetHashCode();
Tree.PackageTypeHashToInstance[packageTypeHash] = package;
Tree.PackageTypeHashToComponentTypeHashDependencies[packageTypeHash] = new List<int>();
return new CoreRegistration(this, packageTypeHash);
return PackageRegistry.RegisterPackage(package);
}
/// <summary>

/// The component instance to register.
/// </param>
/// <typeparam name="T">
/// <typeparam name="TComponent">
public void RegisterServiceComponent<T>(T component)
where T : IServiceComponent
[SuppressMessage("ReSharper", "RedundantTypeArgumentsOfMethod")]
public void RegisterServiceComponent<TComponent>(
[NotNull] TComponent component)
where TComponent : IServiceComponent
if (IsComponentRegistrationLocked)
{
throw new InvalidOperationException(k_LockedComponentRegistrationErrorMessage);
}
var componentType = typeof(T);
// 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 ArgumentException(
$"A component with the type {componentType.FullName} have already been registered.");
}
ComponentTypeHashToInstance[componentTypeHash] = component;
ComponentRegistry.RegisterServiceComponent<TComponent>(component);
/// <typeparam name="T">
/// <typeparam name="TComponent">
/// The type of <see cref="IServiceComponent"/> to get.
/// </typeparam>
/// <returns>

/// <exception cref="KeyNotFoundException">
/// Thrown if the requested type of <typeparamref name="T"/> hasn't been registered yet.
/// Thrown if the requested type of <typeparamref name="TComponent"/> hasn't been registered yet.
public T GetServiceComponent<T>()
where T : IServiceComponent
{
var componentType = typeof(T);
if (!ComponentTypeHashToInstance.TryGetValue(componentType.GetHashCode(), out var component)
|| component == MissingComponent.Instance)
{
throw new KeyNotFoundException($"There is no component `{componentType.Name}` registered. " +
"Are you missing a package?");
}
return (T)component;
}
internal void RegisterDependency<TComponent>(int packageTypeHash)
[NotNull]
public TComponent GetServiceComponent<TComponent>()
if (IsPackageRegistrationLocked)
{
throw new InvalidOperationException(k_LockedPackageRegistrationErrorMessage);
}
var componentTypeHash = typeof(TComponent).GetHashCode();
ComponentTypeHashToInstance[componentTypeHash] = MissingComponent.Instance;
AddComponentDependencyToPackage(componentTypeHash, packageTypeHash);
}
internal void RegisterOptionalDependency<TComponent>(int packageTypeHash)
where TComponent : IServiceComponent
{
if (IsPackageRegistrationLocked)
{
throw new InvalidOperationException(k_LockedPackageRegistrationErrorMessage);
}
var componentTypeHash = typeof(TComponent).GetHashCode();
if (!ComponentTypeHashToInstance.ContainsKey(componentTypeHash))
{
ComponentTypeHashToInstance[componentTypeHash] = null;
}
AddComponentDependencyToPackage(componentTypeHash, packageTypeHash);
return ComponentRegistry.GetServiceComponent<TComponent>();
internal void RegisterProvision<TComponent>(int packageTypeHash)
where TComponent : IServiceComponent
internal void LockPackageRegistration()
if (IsPackageRegistrationLocked)
if (PackageRegistry is LockedPackageRegistry)
throw new InvalidOperationException(k_LockedPackageRegistrationErrorMessage);
return;
var componentTypeHash = typeof(TComponent).GetHashCode();
Tree.ComponentTypeHashToPackageTypeHash[componentTypeHash] = packageTypeHash;
}
internal void LockPackageRegistration()
{
IsPackageRegistrationLocked = true;
PackageRegistry = new LockedPackageRegistry(PackageRegistry);
IsComponentRegistrationLocked = true;
}
void AddComponentDependencyToPackage(int componentTypeHash, int packageTypeHash)
{
var dependencyTypeHashs = Tree.PackageTypeHashToComponentTypeHashDependencies[packageTypeHash];
if (!dependencyTypeHashs.Contains(componentTypeHash))
if (ComponentRegistry is LockedComponentRegistry)
dependencyTypeHashs.Add(componentTypeHash);
return;
}
bool IsComponentTypeRegistered(int componentTypeHash)
{
return ComponentTypeHashToInstance.TryGetValue(componentTypeHash, out var storedComponent)
&& !(storedComponent is null)
&& storedComponent != MissingComponent.Instance;
ComponentRegistry = new LockedComponentRegistry(ComponentRegistry);
}
}
}

8
Packages/com.unity.services.core/Runtime/Core.Internal/Registry/CoreRegistryInitializer.cs


using System.Collections.Generic;
using System.Threading.Tasks;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Helper object to initialize all <see cref="IInitializablePackage"/> registered in a <see cref="CoreRegistry"/>.

if (m_SortedPackageTypeHashes.Count <= 0)
{
CompleteInitialization();
return;
}

|| m_PackageInitializationFailureReasons.Count <= 0)
{
m_Operation.Succeed();
m_Registry.Tree = null;
}
else
{

m_Operation.Fail(reason);
}
m_Registry.PackageRegistry.Tree = null;
m_PackageInitializationFailureReasons = null;
}

IInitializablePackage GetPackageAt(int index)
{
var packageTypeHash = m_SortedPackageTypeHashes[index];
return m_Registry.Tree.PackageTypeHashToInstance[packageTypeHash];
return m_Registry.PackageRegistry.Tree.PackageTypeHashToInstance[packageTypeHash];
}
}
}

7
Packages/com.unity.services.core/Runtime/Core.Internal/Registry/DependencyTree.cs


using System.Collections.Generic;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Contain dependency relations between <see cref="IInitializablePackage"/>

/// </summary>
public Dictionary<int, List<int>> PackageTypeHashToComponentTypeHashDependencies;
/// <inheritdoc cref="CoreRegistry.ComponentTypeHashToInstance"/>
/// <summary>
/// Key: Hash code of a <see cref="IServiceComponent"/> type.
/// Value: Component instance.
/// </summary>
public readonly Dictionary<int, IServiceComponent> ComponentTypeHashToInstance;
internal DependencyTree()

2
Packages/com.unity.services.core/Runtime/Core.Internal/Registry/DependencyTreeInitializeOrderSorter.cs


using System.Collections.Generic;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Helper object to sort <see cref="IInitializablePackage"/> stored into a

2
Packages/com.unity.services.core/Runtime/Core.Internal/Registry/IInitializablePackage.cs


using System.Threading.Tasks;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Contract for objects able to register a set of <see cref="IServiceComponent"/>

2
Packages/com.unity.services.core/Runtime/Core.Internal/Registry/IServiceComponent.cs


namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Base contract for a functionality defined by the Core package.

2
Packages/com.unity.services.core/Runtime/Core.Internal/Registry/MissingComponent.cs


namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Placeholder for required <see cref="IServiceComponent"/> registered into a <see cref="CoreRegistry"/>.

80
Packages/com.unity.services.core/Runtime/Core.Internal/Unity.Services.Core.Internal.api


// 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.Authentication
namespace Unity.Services.Authentication.Internal
public interface IAccessToken : Unity.Services.Core.IServiceComponent
public interface IAccessToken : Unity.Services.Core.Internal.IServiceComponent
public interface IPlayerId : Unity.Services.Core.IServiceComponent
public interface IPlayerId : Unity.Services.Core.Internal.IServiceComponent
{
public event System.Action<string> PlayerIdChanged;
public abstract string PlayerId { get; }

namespace Unity.Services.Core
namespace Unity.Services.Core.Configuration.Internal
public class CircularDependencyException : Unity.Services.Core.ServicesInitializationException
public interface IProjectConfiguration : Unity.Services.Core.Internal.IServiceComponent
public CircularDependencyException() {}
public CircularDependencyException(string message) {}
public abstract bool GetBool(string key, bool defaultValue = False);
public abstract float GetFloat(string key, float defaultValue = 0);
public abstract int GetInt(string key, int defaultValue = 0);
public abstract string GetString(string key, string defaultValue = default(string));
}
[System.Runtime.CompilerServices.IsReadOnly] public struct CoreRegistration
namespace Unity.Services.Core.Device.Internal
{
public interface IInstallationId : Unity.Services.Core.Internal.IServiceComponent
public Unity.Services.Core.CoreRegistration DependsOn<T>() where T : Unity.Services.Core.IServiceComponent;
public Unity.Services.Core.CoreRegistration OptionallyDependsOn<T>() where T : Unity.Services.Core.IServiceComponent;
public Unity.Services.Core.CoreRegistration ProvidesComponent<T>() where T : Unity.Services.Core.IServiceComponent;
public abstract string GetOrCreateIdentifier();
}
public sealed class CoreRegistry
namespace Unity.Services.Core.Environments.Internal
{
public interface IEnvironments : Unity.Services.Core.Internal.IServiceComponent
public static Unity.Services.Core.CoreRegistry Instance { get; }
public T GetServiceComponent<T>() where T : Unity.Services.Core.IServiceComponent;
public Unity.Services.Core.CoreRegistration RegisterPackage<T>(T package) where T : Unity.Services.Core.IInitializablePackage;
public void RegisterServiceComponent<T>(T component) where T : Unity.Services.Core.IServiceComponent;
public abstract string Current { get; }
}
public interface IInitializablePackage
namespace Unity.Services.Core.Internal
{
public class CircularDependencyException : Unity.Services.Core.ServicesInitializationException
public abstract System.Threading.Tasks.Task Initialize(Unity.Services.Core.CoreRegistry registry);
public CircularDependencyException() {}
public CircularDependencyException(string message) {}
public interface IServiceComponent
public struct CoreRegistration
public Unity.Services.Core.Internal.CoreRegistration DependsOn<T>() where T : Unity.Services.Core.Internal.IServiceComponent;
public Unity.Services.Core.Internal.CoreRegistration OptionallyDependsOn<T>() where T : Unity.Services.Core.Internal.IServiceComponent;
public Unity.Services.Core.Internal.CoreRegistration ProvidesComponent<T>() where T : Unity.Services.Core.Internal.IServiceComponent;
}
namespace Unity.Services.Core.Configuration
{
public interface IProjectConfiguration : Unity.Services.Core.IServiceComponent
public sealed class CoreRegistry
public abstract bool GetBool(string key, bool defaultValue = False);
public abstract float GetFloat(string key, float defaultValue = 0);
public abstract int GetInt(string key, int defaultValue = 0);
public abstract string GetString(string key, string defaultValue = default(string));
public static Unity.Services.Core.Internal.CoreRegistry Instance { get; }
[JetBrains.Annotations.NotNull] public TComponent GetServiceComponent<TComponent>() where TComponent : Unity.Services.Core.Internal.IServiceComponent;
public Unity.Services.Core.Internal.CoreRegistration RegisterPackage<TPackage>([JetBrains.Annotations.NotNull] TPackage package) where TPackage : Unity.Services.Core.Internal.IInitializablePackage;
public void RegisterServiceComponent<TComponent>([JetBrains.Annotations.NotNull] TComponent component) where TComponent : Unity.Services.Core.Internal.IServiceComponent;
}
namespace Unity.Services.Core.Device
{
public interface IInstallationId : Unity.Services.Core.IServiceComponent
public interface IInitializablePackage
public abstract string GetOrCreateIdentifier();
public abstract System.Threading.Tasks.Task Initialize(Unity.Services.Core.Internal.CoreRegistry registry);
}
public interface IServiceComponent
{
namespace Unity.Services.Core.Environments
namespace Unity.Services.Privacy.Internal
public interface IEnvironments : Unity.Services.Core.IServiceComponent
public interface IPrivacyConsent : Unity.Services.Core.Internal.IServiceComponent
public abstract string Current { get; }
public event System.Action ConsentStatusChanged;
public abstract bool DoesLegislationApply(Unity.Services.Privacy.Legislation legislation);
public abstract Unity.Services.Privacy.ConsentStatus UserConsentStatus(Unity.Services.Privacy.Legislation legislation);
}
}

16
Packages/com.unity.services.core/Runtime/Core.Internal/UnityServicesInitializer.cs


using Unity.Services.Authentication;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
class UnityServicesInitializer
static class UnityServicesInitializer
static void Initialize()
static void CreateStaticInstance()
UnityServices.Instance = new UnityServicesInternal();
UnityServices.Instance = new UnityServicesInternal(CoreRegistry.Instance);
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
static void EnableServicesInitialization()
{
var instance = (UnityServicesInternal)UnityServices.Instance;
instance.EnableInitialization();
}
}
}

60
Packages/com.unity.services.core/Runtime/Core.Internal/UnityServicesInternal.cs


using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using NotNull = JetBrains.Annotations.NotNullAttribute;
namespace Unity.Services.Core
namespace Unity.Services.Core.Internal
{
/// <summary>
/// Utility to initialize all Unity services from a single endpoint.

/// <summary>
/// Initialization state.
/// </summary>
public ServicesInitializationState State { get; internal set; }
public ServicesInitializationState State { get; private set; }
public InitializationOptions Options { get; internal set; }
public InitializationOptions Options { get; private set; }
internal AsyncOperation Initialization;
AsyncOperation m_Initialization;
[NotNull]
CoreRegistry Registry { get; }
public UnityServicesInternal(
[NotNull] CoreRegistry registry)
{
Registry = registry;
}
/// <summary>
/// Single entry point to initialize all used services.

if (!CanInitialize
|| State != ServicesInitializationState.Uninitialized)
{
return Initialization.AsTask();
return m_Initialization.AsTask();
return Initialization.AsTask();
return m_Initialization.AsTask();
return !(Initialization is null);
return !(m_Initialization is null);
return Initialization.Status == AsyncOperationStatus.Failed;
return m_Initialization.Status == AsyncOperationStatus.Failed;
Initialization = new AsyncOperation();
Initialization.SetInProgress();
Initialization.Completed += OnInitializationCompleted;
m_Initialization = new AsyncOperation();
m_Initialization.SetInProgress();
m_Initialization.Completed += OnInitializationCompleted;
var registry = CoreRegistry.Instance;
var sortedPackageTypeHashes = new List<int>(registry.Tree.PackageTypeHashToInstance.Count);
var sortedPackageTypeHashes = new List<int>(
Registry.PackageRegistry.Tree?.PackageTypeHashToInstance.Count ?? 0);
var sorter = new DependencyTreeInitializeOrderSorter(registry.Tree, sortedPackageTypeHashes);
var sorter = new DependencyTreeInitializeOrderSorter(
Registry.PackageRegistry.Tree, sortedPackageTypeHashes);
Initialization.Fail(reason);
m_Initialization.Fail(reason);
return;
}

var initializer = new CoreRegistryInitializer(registry, Initialization, sortedPackageTypeHashes);
var initializer = new CoreRegistryInitializer(Registry, m_Initialization, sortedPackageTypeHashes);
Initialization.Fail(reason);
m_Initialization.Fail(reason);
}
}

case AsyncOperationStatus.Succeeded:
{
State = ServicesInitializationState.Initialized;
CoreRegistry.Instance.LockComponentRegistration();
Registry.LockComponentRegistration();
break;
}

}
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
internal static void EnableInitialization()
internal void EnableInitialization()
var instance = (UnityServicesInternal)UnityServices.Instance;
CanInitialize = true;
instance.CanInitialize = true;
CoreRegistry.Instance.LockPackageRegistration();
Registry.LockPackageRegistration();
if (instance.HasRequestedInitialization())
if (HasRequestedInitialization())
instance.StartInitialization();
StartInitialization();
}
}
}

19
Packages/com.unity.services.core/Runtime/Core/Unity.Services.Core.api


public static System.Threading.Tasks.Task Initialize(Unity.Services.Core.InitializationOptions options);
}
}
namespace Unity.Services.Privacy
{
public enum ConsentStatus
{
public const Unity.Services.Privacy.ConsentStatus NotRequested = 0;
public const Unity.Services.Privacy.ConsentStatus OptedIn = 1;
public const Unity.Services.Privacy.ConsentStatus OptedOut = 2;
public int value__;
}
public enum Legislation
{
public const Unity.Services.Privacy.Legislation CCPA = 1;
public const Unity.Services.Privacy.Legislation GDPR = 2;
public const Unity.Services.Privacy.Legislation None = 0;
public int value__;
}
}

2
Packages/com.unity.services.core/Runtime/Core/Unity.Services.Core.api.meta


fileFormatVersion: 2
guid: 295d3524c32b2aa4d965b9308be33e37
guid: 75ba8cc18b7164eb6aa7a8c4e64fbd25
DefaultImporter:
externalObjects: {}
userData:

8
Packages/com.unity.services.core/Runtime/Core/UnityServices.cs


using System.Threading.Tasks;
using UnityEngine;
namespace Unity.Services.Core
{

/// </returns>
public static Task Initialize(InitializationOptions options)
{
if (!Application.isPlaying)
{
return Task.FromException(
new ServicesInitializationException("You are attempting to initialize Unity Services in Edit Mode." +
" Unity Services can only be initialized in Play Mode"));
}
if (Instance == null)
{
return Task.FromException(

12
Packages/com.unity.services.core/Runtime/Device/UserIdProviders/AndroidUtils.cs


using System;
using UnityEngine;
namespace Unity.Services.Core.Device.Internal
namespace Unity.Services.Core.Device
const int ContextModePrivate = 0x0000;
const int k_ContextModePrivate = 0x0000;
public static AndroidJavaObject GetUnityActivity()
{

}
}
public static AndroidJavaObject GetSharedPreferences(AndroidJavaObject context, string name, int mode = ContextModePrivate)
public static AndroidJavaObject GetSharedPreferences(AndroidJavaObject context, string name, int mode = k_ContextModePrivate)
public static AndroidJavaObject GetSharedPreferences(string name, int mode = ContextModePrivate)
public static AndroidJavaObject GetSharedPreferences(string name, int mode = k_ContextModePrivate)
{
using (var activity = GetUnityActivity())
{

return;
var editor = preferences.Call<AndroidJavaObject>("edit");
editor.Call("putString", key, value);
editor.Call("commit");
editor.Call<AndroidJavaObject>("putString", key, value);
editor.Call<bool>("commit");
}
}
}

2
Packages/com.unity.services.core/Runtime/Device/UserIdProviders/NSUserDefaults.cs


#if UNITY_IOS
using System.Runtime.InteropServices;
namespace Unity.Services.Core.Device.Internal
namespace Unity.Services.Core.Device
{
class NSUserDefaults
{

4
Packages/com.unity.services.core/Runtime/Device/UserIdProviders/UnityAdsIdentifier.cs


using UnityEngine;
namespace Unity.Services.Core.Device.Internal
namespace Unity.Services.Core.Device
{
class UnityAdsIdentifier : IUserIdentifierProvider
{

2
Packages/com.unity.services.core/Runtime/Device/UserIdProviders/UnityAnalyticsIdentifier.cs


using System;
using UnityEngine;
namespace Unity.Services.Core.Device.Internal
namespace Unity.Services.Core.Device
{
class UnityAnalyticsIdentifier : IUserIdentifierProvider
{

2
Packages/com.unity.services.core/Runtime/Device/UserIdProviders/IUserIdentifierProvider.cs


namespace Unity.Services.Core.Device.Internal
namespace Unity.Services.Core.Device
{
interface IUserIdentifierProvider
{

7
Packages/com.unity.services.core/Runtime/Environments/Unity.Services.Core.Environments.api


// 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.Environments
{
[System.Runtime.CompilerServices.Extension] public static class EnvironmentsOptionsExtensions
{
[System.Runtime.CompilerServices.Extension] public static Unity.Services.Core.InitializationOptions SetEnvironmentName(Unity.Services.Core.InitializationOptions self, string environmentName);
}
}

8
Packages/com.unity.services.core/Runtime/Environments/Unity.Services.Core.Environments.asmdef


{
"name": "Unity.Services.Core.Environments",
"rootNamespace": "",
"Unity.Services.Core.Internal"
"Unity.Services.Core.Internal",
"Unity.Services.Core"
],
"includePlatforms": [],
"excludePlatforms": [],

"autoReferenced": false,
"autoReferenced": true,
}
}

1
Packages/com.unity.services.core/Runtime/Networking/HttpServiceConfig.cs


using System;
using Unity.Services.Core.Networking.Internal;
namespace Unity.Services.Core.Networking
{

2
Packages/com.unity.services.core/Runtime/Networking/UnityWebRequestClient.cs


using System.Collections.Generic;
using System.IO;
using UnityEngine.Networking;
using Unity.Services.Core.Internal;
using Unity.Services.Core.Networking.Internal;
namespace Unity.Services.Core.Networking
{

28
Packages/com.unity.services.core/Runtime/Registration/CorePackageInitializer.cs


using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Services.Core.Configuration;
using Unity.Services.Core.Configuration.Internal;
using Unity.Services.Core.Device.Internal;
using Unity.Services.Core.Environments.Internal;
using Unity.Services.Core.Internal;
using NotNull = JetBrains.Annotations.NotNullAttribute;
namespace Unity.Services.Core.Registration
{

/// </returns>
public async Task Initialize(CoreRegistry registry)
{
// There are potential race conditions with other services we're trying to avoid by calling
// RegisterInstallationId as the _very first_ thing we do.
RegisterEnvironments(registry);
await RegisterProjectConfigurationAsync(registry);
var projectConfiguration = await RegisterProjectConfigurationAsync(
registry, UnityServices.Instance.Options);
RegisterEnvironments(registry, projectConfiguration);
}
internal static void RegisterInstallationId(CoreRegistry registry)

registry.RegisterServiceComponent<IInstallationId>(installationId);
}
internal static void RegisterEnvironments(CoreRegistry registry)
internal static void RegisterEnvironments(CoreRegistry registry, IProjectConfiguration projectConfiguration)
var environments = new Environments.Environments();
var environments = new Environments.Internal.Environments();
environments.Current = projectConfiguration.GetString(EnvironmentsOptionsExtensions.EnvironmentNameKey, "production");
internal static async Task RegisterProjectConfigurationAsync(CoreRegistry registry)
internal static async Task<IProjectConfiguration> RegisterProjectConfigurationAsync(
[NotNull] CoreRegistry registry,
[NotNull] InitializationOptions options)
var options = UnityServices.Instance.Options;
return projectConfig;
InitializationOptions options)
[NotNull] InitializationOptions options)
{
var serializedConfig = await GetSerializedConfigOrEmptyAsync();
var configValues = new Dictionary<string, ConfigurationEntry>(serializedConfig.Keys.Length);

}
catch (Exception e)
{
Debug.LogError(
CoreLogger.LogError(
"En error occured while trying to get the project configuration for services." +
$"\n{e.Message}" +
$"\n{e.StackTrace}");

3
Packages/com.unity.services.core/Runtime/Registration/Unity.Services.Core.Registration.asmdef


"Unity.Services.Core.Internal",
"Unity.Services.Core.Device",
"Unity.Services.Core.Environments",
"Unity.Services.Core.Environments.Internal",
"Unity.Services.Core.Configuration",
"Unity.Services.Core"
],

"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
}

11
Packages/com.unity.services.core/package.json


{
"name": "com.unity.services.core",
"displayName": "Services Core",
"version": "1.1.0-pre.2",
"version": "1.1.0-pre.4",
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.nuget.newtonsoft-json": "2.0.0"
"com.unity.modules.unitywebrequest": "1.0.0"
"com.unity.services.core.tests": "1.1.0-pre.2"
"com.unity.services.core.tests": "1.1.0-pre.4"
"footprint": "187a0fc7bf76eaef62cb959fb5d0873dde9c81b0"
"footprint": "2087c58489377c591143067b3823dcb95ae0d0dd"
"revision": "54737111b425289a3e8540a7ffe6bd4cdfbaf535"
"revision": "13eac0cd38d1a3ff7f8099590c524a7043817cb2"
}
}

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存