using System.Collections.Generic; using UnityEngine; using Ubisoft.Hotel.Addressables.Core.Editor; namespace Ubisoft.Hotel.Package.Editor { public class AddressablesBuildProperty : PackageProperty { [System.Serializable] public class RemoteHostSettings { protected const string TOKEN_PLATFORM = "[Platform]"; protected const string TOKEN_GAME_VERSION = "[GameVersion]"; private string m_buildPath; private string m_loadPath; private string m_urlSuffix; private string m_bucketId; public static string GetDefaultBuildPath() { return $"{BuildProcessorConstants.REMOTE_ASSET_BUNDLES_PATH}/{TOKEN_PLATFORM}"; } public RemoteHostSettings(string buildPath, string loadPath, string urlSuffix, string bucketId) { BuildPath = buildPath; LoadPath = loadPath; UrlSuffix = urlSuffix; BucketId = bucketId; } public RemoteHostSettings(RemoteHostSettings other) : this(other.BuildPath, other.LoadPath, other.UrlSuffix, other.BucketId) { } public void Clear() { BuildPath = null; LoadPath = null; UrlSuffix = null; BucketId = null; } public string BuildPath { get { return m_buildPath; } private set { m_buildPath = value; } } public string LoadPath { get { return m_loadPath; } private set { m_loadPath = value; } } public string GetCustomBuildPath(string platform, string gameVersion) { return CustomiseSetting(BuildPath, platform, gameVersion); } public string GetCustomLoadPath(string platform, string gameVersion) { return CustomiseSetting(LoadPath, platform, gameVersion); } public string GetCustomUrlSuffix(string platform, string gameVersion) { return CustomiseSetting(UrlSuffix, platform, gameVersion); } private string CustomiseSetting(string value, string platform, string gameVersion) { string returnValue = value; returnValue = returnValue.Replace(TOKEN_PLATFORM, platform); returnValue = returnValue.Replace(TOKEN_GAME_VERSION, gameVersion); return returnValue; } public string UrlSuffix { get { return m_urlSuffix; } private set { m_urlSuffix = value; } } public string BucketId { get { return m_bucketId; } private set { m_bucketId = value; } } public bool IsEmpty() { return LoadPath == null; } public override bool Equals(object obj) { RemoteHostSettings other = (RemoteHostSettings)obj; return other.BuildPath.Equals(BuildPath) && other.LoadPath.Equals(LoadPath) && other.UrlSuffix.Equals(UrlSuffix) && other.BucketId.Equals(BucketId); } public override int GetHashCode() { unchecked // Allow arithmetic overflow, numbers will just "wrap around" { int hashcode = 1430287; hashcode = (hashcode * 7302013) ^ BuildPath.GetHashCode(); hashcode = (hashcode * 7302013) ^ LoadPath.GetHashCode(); hashcode = (hashcode * 7302013) ^ UrlSuffix.GetHashCode(); hashcode = (hashcode * 7302013) ^ BucketId.GetHashCode(); return hashcode; } } public override string ToString() { return $"BuildPath: {BuildPath}, LoadPath: {LoadPath}, UrlSuffix: {UrlSuffix}, BucketId {BucketId}"; } } public class UbisoftCdnSettings : RemoteHostSettings { private const string URL_ROOT = "https://ubistatic-a.akamaihd.net"; private static string GetSuffix(string branchName) { return $"root/{branchName}/{TOKEN_GAME_VERSION}/{TOKEN_PLATFORM}"; } public UbisoftCdnSettings(string bucketId, string branchName, string buildPath = null) : base(string.IsNullOrEmpty(buildPath) ? GetDefaultBuildPath() : buildPath, $"{URL_ROOT}/{bucketId}/{GetSuffix(branchName)}", GetSuffix(branchName), bucketId) { } } public class UnityHostSettings : RemoteHostSettings { public UnityHostSettings() : base(GetDefaultBuildPath(), "http://[PrivateIpAddress]:[HostingServicePort]/", "", "") { } } public static AddressablesBuildProperty CreateInstanceWithParams(string name) { AddressablesBuildProperty returnValue = CreateInstance(); returnValue.name = name; return returnValue; } /// /// When enabled remote asset bundles are stored in the store CDN. /// When disabled remote asset bundles need to be stored to a CDN that is handled by the game. /// [SerializeField] private EBoolean m_useStoreCdn; /// /// When enabled all addressables group will be included in the build, typically to be able /// to share a build without having to upload remote (FastFollow and OnDemand) asset bundles. /// [SerializeField] private EBoolean m_useAllInstallTime; /// /// List of group names to exclude from build. /// [SerializeField] private List m_groupNamesToExcludeFromBuild; /// /// List of group labels to exclude from build. /// [SerializeField] private List m_groupLabelsToExcludeFromBuild; /// /// Remote host configuration. /// [SerializeField] private RemoteHostSettings m_remoteHostSettings; public EBoolean UseStoreCdn { get { return m_useStoreCdn; } set { m_useStoreCdn = value; } } public EBoolean UseAllInstallTime { get { return m_useAllInstallTime; } set { m_useAllInstallTime = value; } } private List GroupNamesToExcludeFromBuild { get { return m_groupNamesToExcludeFromBuild; } set { m_groupNamesToExcludeFromBuild = value; } } private List GroupLabelsToExcludeFromBuild { get { return m_groupLabelsToExcludeFromBuild; } set { m_groupLabelsToExcludeFromBuild = value; } } public RemoteHostSettings HostSettings { get { return m_remoteHostSettings; } set { m_remoteHostSettings = value; } } public void Clear() { UseStoreCdn = EBoolean.AsUnitySettings; UseAllInstallTime = EBoolean.AsUnitySettings; GroupNamesToExcludeFromBuild = new List(); GroupLabelsToExcludeFromBuild = new List(); HostSettings?.Clear(); } public override void Apply(BuildSuite buildSuite) { if (buildSuite != null) { buildSuite.OrderProperty(this); GenerateAddressablesBuildSettings(buildSuite.Platform, buildSuite.GameVersion); if (UseStoreCdn == EBoolean.True) { UnityBuildProperty unityProperty = UnityBuildProperty.CreateInstanceWithParams($"{name}_unity"); buildSuite.OrderProperty(unityProperty); unityProperty.AddDefineSymbol(UnityBuildProperty.SYMBOLS_HT_ADDRESSABLES_STORE_CDN_ON); } } } public void Join(AddressablesBuildProperty p) { if (p != null) { if (p.UseStoreCdn != EBoolean.AsUnitySettings) { if (UseStoreCdn == EBoolean.AsUnitySettings) { UseStoreCdn = p.UseStoreCdn; } else if (UseStoreCdn != p.UseStoreCdn) { Log($"Can't assign {Debug.FormatTextInUserContext(p.UseStoreCdn.ToString())} as UseDynamicAssetDelivery " + $" because there is already a valid value assigned: {Debug.FormatTextInUserContext(UseStoreCdn.ToString())}", ELogLevel.Error); } } if (p.UseAllInstallTime != EBoolean.AsUnitySettings) { if (UseAllInstallTime == EBoolean.AsUnitySettings) { UseAllInstallTime = p.UseAllInstallTime; } else if (UseAllInstallTime != p.UseAllInstallTime) { Log($"Can't assign {Debug.FormatTextInUserContext(p.UseAllInstallTime.ToString())} as UseAllInstallTime " + $" because there is already a valid value assigned: {Debug.FormatTextInUserContext(UseAllInstallTime.ToString())}", ELogLevel.Error); } } if (p.GroupNamesToExcludeFromBuild != null) { for (int i = 0; i < p.GroupNamesToExcludeFromBuild.Count; ++i) { if (!GroupNamesToExcludeFromBuild.Contains(p.GroupNamesToExcludeFromBuild[i])) { GroupNamesToExcludeFromBuild.Add(p.GroupNamesToExcludeFromBuild[i]); } } } if (p.GroupLabelsToExcludeFromBuild != null) { for (int i = 0; i < p.GroupLabelsToExcludeFromBuild.Count; ++i) { if (!GroupLabelsToExcludeFromBuild.Contains(p.GroupLabelsToExcludeFromBuild[i])) { GroupLabelsToExcludeFromBuild.Add(p.GroupLabelsToExcludeFromBuild[i]); } } } if (p.HostSettings != null && !p.HostSettings.IsEmpty()) { if (HostSettings == null || HostSettings.IsEmpty()) { HostSettings = new RemoteHostSettings(p.HostSettings); } else if (HostSettings != null && !HostSettings.Equals(p.HostSettings)) { Log($"Can't assign {Debug.FormatTextInUserContext(p.HostSettings.ToString())} as HostSettings " + $" because there is already a valid value assigned: {Debug.FormatTextInUserContext(HostSettings.ToString())}", ELogLevel.Error); } } } } public void PreBuild() { } public void PostBuild() { } public void ExcludeGroupNamesFromBuild(HashSet groupNames) { if (groupNames != null) { foreach (string groupName in groupNames) { if (GroupNamesToExcludeFromBuild == null || !GroupNamesToExcludeFromBuild.Contains(groupName)) { if (GroupNamesToExcludeFromBuild == null) { GroupNamesToExcludeFromBuild = new List(); } GroupNamesToExcludeFromBuild.Add(groupName); } } } } public void ExcludeGroupLabelsFromBuild(HashSet groupLabels) { if (groupLabels != null) { foreach (string groupLabel in groupLabels) { if (GroupLabelsToExcludeFromBuild == null || !GroupLabelsToExcludeFromBuild.Contains(groupLabel)) { if (GroupLabelsToExcludeFromBuild == null) { GroupLabelsToExcludeFromBuild = new List(); } GroupLabelsToExcludeFromBuild.Add(groupLabel); } } } } private void GenerateAddressablesBuildSettings(EPlatform platform, Version gameVersion) { AddressablesBuildSettings settings = AddressablesBuildSettings.GetSettings(true); settings.Reset(); settings.UseStoreCdn = UseStoreCdn == EBoolean.True; settings.UseAllInstallTime = UseAllInstallTime == EBoolean.True; if (HostSettings != null) { string platformAsString = PlatformUtils.EPlatformToKey(platform); string gameVersionAsString = gameVersion == null ? "0.0" : $"{gameVersion.Major}.{gameVersion.Minor}"; settings.HostRemoteBuildPath = HostSettings.GetCustomBuildPath(platformAsString, gameVersionAsString); settings.HostRemoteLoadPath = HostSettings.GetCustomLoadPath(platformAsString, gameVersionAsString); settings.HostRemoteUrlSuffix = HostSettings.GetCustomUrlSuffix(platformAsString, gameVersionAsString); settings.HostRemoteBucketId = HostSettings.BucketId; } if (GroupNamesToExcludeFromBuild != null) { settings.ExcludeGroupNamesFromBuild(GroupNamesToExcludeFromBuild); } if (GroupLabelsToExcludeFromBuild != null) { settings.ExcludeGroupLabelsFromBuild(GroupLabelsToExcludeFromBuild); } UnityEditor.EditorUtility.SetDirty(settings); UnityEditor.AssetDatabase.SaveAssets(); } } }