using System; using Unity.Multiplayer.Center.Questionnaire; using UnityEditor.PackageManager; using UnityEngine; namespace Unity.Multiplayer.Center.Recommendations { [Serializable] internal class PreReleaseHandling { [SerializeReference] PreReleaseHandlingBase[] m_PreReleaseHandlings = { }; public event Action OnAllChecksFinished; public bool IsReady => m_PreReleaseHandlings != null && Array.TrueForAll(m_PreReleaseHandlings, p => p is {IsReady: true}); public void CheckForUpdates() { foreach (var package in m_PreReleaseHandlings) { package.OnCheckFinished += OnOnePackageVersionCheckFinished; package.CheckForUpdates(); } } public void PatchPackages(RecommendationViewData toPatch) { foreach (var package in m_PreReleaseHandlings) { package.PatchPackages(toPatch); } } public void PatchRecommenderSystemData() { foreach (var package in m_PreReleaseHandlings) { package.PatchRecommenderSystemData(); } } void OnOnePackageVersionCheckFinished() { var allVersionChecksDone = true; foreach (var package in m_PreReleaseHandlings) { allVersionChecksDone &= package.IsReady; if (package.IsReady) { package.OnCheckFinished -= OnOnePackageVersionCheckFinished; } } if (allVersionChecksDone) { OnAllChecksFinished?.Invoke(); } } } [Serializable] internal abstract class PreReleaseHandlingBase { /// /// Whether the versions data is ready to be used. /// public bool IsReady => m_VersionsInfo != null && !string.IsNullOrEmpty(m_VersionsInfo.latestCompatible); /// /// Triggered when this instance is ready /// public event Action OnCheckFinished; /// /// The package id e.g. com.unity.netcode /// public abstract string PackageId { get; } /// /// The minimum version that we target. /// public abstract string MinVersion { get; } /// /// The cached versions of the package. /// [SerializeField] protected VersionsInfo m_VersionsInfo; /// /// version which would be installed by package manager /// [SerializeField] protected string m_DefaultVersion; PackageManagement.VersionChecker m_VersionChecker; /// /// Start (online) request to check for available versions. /// public void CheckForUpdates() { m_VersionChecker = new PackageManagement.VersionChecker(PackageId); m_VersionChecker.OnVersionFound += OnVersionFound; } internal string GetPreReleaseVersion(string version, VersionsInfo versionsInfo) { if (version != null && version.StartsWith(MinVersion)) return null; // no need for a pre-release version return versionsInfo.latestCompatible.StartsWith(MinVersion) ? versionsInfo.latestCompatible : null; } /// /// Patch the recommendation view data directly. /// /// The view data to patch public abstract void PatchPackages(RecommendationViewData toPatch); /// /// Patch the recommender system data, which will be used for every use of the recommendation. /// public abstract void PatchRecommenderSystemData(); protected virtual void BeforeRaisingCheckFinished() { } void OnVersionFound(PackageInfo packageInfo) { m_DefaultVersion = packageInfo.version; m_VersionsInfo = packageInfo.versions; if (m_VersionChecker != null) // null observed in tests m_VersionChecker.OnVersionFound -= OnVersionFound; m_VersionChecker = null; BeforeRaisingCheckFinished(); OnCheckFinished?.Invoke(); } } /// /// Implementation that fetches unconditionally the version starting with a prefix for a given package, even if it /// is an experimental package /// [Serializable] internal class SimplePreReleaseHandling : PreReleaseHandlingBase { [SerializeField] string m_MinVersion; [SerializeField] string m_PackageId; public override string MinVersion => m_MinVersion; public override string PackageId => m_PackageId; public SimplePreReleaseHandling(string packageId, string minVersion) { m_PackageId = packageId; m_MinVersion = minVersion; } private SimplePreReleaseHandling() { } public override void PatchPackages(RecommendationViewData toPatch) { // Nothing to do, we only patch the package details in the recommender system data } public override void PatchRecommenderSystemData() { if (!IsReady) return; var allPackages = RecommenderSystemDataObject.instance.RecommenderSystemData.Packages; foreach (var package in allPackages) { if (package.Id == PackageId) { package.PreReleaseVersion = GetPreReleaseVersion(m_DefaultVersion, m_VersionsInfo); } } } } }