diff --git a/Basis/Packages/com.basis.bundlemanagement/BasisIOManagement.cs b/Basis/Packages/com.basis.bundlemanagement/BasisIOManagement.cs index 86e5e5c66..c3b9053b8 100644 --- a/Basis/Packages/com.basis.bundlemanagement/BasisIOManagement.cs +++ b/Basis/Packages/com.basis.bundlemanagement/BasisIOManagement.cs @@ -43,12 +43,12 @@ public static string NormalizeCachePlatformName(string platformName) public static string GetBeeCacheFilePath(string uniqueVersion, string downloadedPlatform = null) { - return GenerateFilePath(BuildPlatformAwareCacheFileName(uniqueVersion, BasisBeeConstants.BasisEncryptedExtension, downloadedPlatform), BasisBeeConstants.AssetBundlesFolder); + return GenerateFilePath(BuildLegacyCacheFileName(uniqueVersion, BasisBeeConstants.BasisEncryptedExtension), GetPlatformCacheFolder(downloadedPlatform)); } public static string GetMetaCacheFilePath(string uniqueVersion, string downloadedPlatform = null) { - return GenerateFilePath(BuildPlatformAwareCacheFileName(uniqueVersion, BasisBeeConstants.BasisMetaExtension, downloadedPlatform), BasisBeeConstants.AssetBundlesFolder); + return GenerateFilePath(BuildLegacyCacheFileName(uniqueVersion, BasisBeeConstants.BasisMetaExtension), GetPlatformCacheFolder(downloadedPlatform)); } public static string GetLegacyBeeCacheFilePath(string uniqueVersion) @@ -61,21 +61,26 @@ public static string GetLegacyMetaCacheFilePath(string uniqueVersion) return GenerateFilePath($"{uniqueVersion}{BasisBeeConstants.BasisMetaExtension}", BasisBeeConstants.AssetBundlesFolder); } - private static string BuildPlatformAwareCacheFileName(string uniqueVersion, string extension, string downloadedPlatform) + private static string GetPlatformCacheFolder(string downloadedPlatform) { - if (string.IsNullOrWhiteSpace(uniqueVersion)) - throw new ArgumentException("Unique version is null or empty.", nameof(uniqueVersion)); - string normalizedPlatform = string.IsNullOrWhiteSpace(downloadedPlatform) ? GetCurrentCachePlatform() : NormalizeCachePlatformName(downloadedPlatform); - foreach (char invalidChar in Path.GetInvalidFileNameChars()) + foreach (char invalidChar in Path.GetInvalidPathChars()) { normalizedPlatform = normalizedPlatform.Replace(invalidChar, '_'); } - return $"{uniqueVersion}.{normalizedPlatform}{extension}"; + return Path.Combine(BasisBeeConstants.AssetBundlesFolder, normalizedPlatform); + } + + private static string BuildLegacyCacheFileName(string uniqueVersion, string extension) + { + if (string.IsNullOrWhiteSpace(uniqueVersion)) + throw new ArgumentException("Unique version is null or empty.", nameof(uniqueVersion)); + + return $"{uniqueVersion}{extension}"; } public sealed class BeeDownloadResult diff --git a/Basis/Packages/com.basis.bundlemanagement/BasisLoadhandler.cs b/Basis/Packages/com.basis.bundlemanagement/BasisLoadhandler.cs index 7fe2b6fc2..bd3337133 100644 --- a/Basis/Packages/com.basis.bundlemanagement/BasisLoadhandler.cs +++ b/Basis/Packages/com.basis.bundlemanagement/BasisLoadhandler.cs @@ -209,60 +209,43 @@ private static bool TryResolveStoredBeePath(BasisBEEExtensionMeta discInfo, out return false; } - private static bool TryLazyLoadDiscInfo(string metaUrl, string currentPlatform, out BasisBEEExtensionMeta info) + private static bool TryLoadDiscInfoFromFile(string filePath, string expectedRemoteUrl, out BasisBEEExtensionMeta info) { info = null; - - string path = BasisIOManagement.GenerateFolderPath(BasisBeeConstants.AssetBundlesFolder); - if (!Directory.Exists(path)) + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) { return false; } - BasisBEEExtensionMeta legacyCandidate = null; - - foreach (string file in Directory.GetFiles(path, $"*{BasisBeeConstants.BasisMetaExtension}")) + try { - try + byte[] fileData = File.ReadAllBytes(filePath); + BasisBEEExtensionMeta discInfo = BasisSerialization.DeserializeValue(fileData); + if (discInfo?.StoredRemote?.RemoteBeeFileLocation == null) { - byte[] fileData = File.ReadAllBytes(file); - BasisBEEExtensionMeta discInfo = BasisSerialization.DeserializeValue(fileData); - if (discInfo?.StoredRemote?.RemoteBeeFileLocation != metaUrl) - { - continue; - } - - OnDiscData[GetDiscInfoKey(discInfo.StoredRemote.RemoteBeeFileLocation, discInfo.DownloadedPlatform)] = discInfo; - - if (!TryResolveStoredBeePath(discInfo, out _)) - { - continue; - } - - if (BasisIOManagement.CachePlatformMatchesCurrent(discInfo.DownloadedPlatform)) - { - info = discInfo; - return true; - } + return false; + } - if (string.IsNullOrWhiteSpace(discInfo.DownloadedPlatform) && legacyCandidate == null) - { - legacyCandidate = discInfo; - } + if (!string.IsNullOrWhiteSpace(expectedRemoteUrl) && + !string.Equals(discInfo.StoredRemote.RemoteBeeFileLocation, expectedRemoteUrl, StringComparison.Ordinal)) + { + return false; } - catch (Exception ex) + + OnDiscData[GetDiscInfoKey(discInfo.StoredRemote.RemoteBeeFileLocation, discInfo.DownloadedPlatform)] = discInfo; + if (!TryResolveStoredBeePath(discInfo, out _)) { - BasisDebug.LogWarning($"Failed lazy-loading disc info from {file}: {ex.Message}", BasisDebug.LogTag.Event); + return false; } - } - if (legacyCandidate != null) - { - info = legacyCandidate; + info = discInfo; return true; } - - return false; + catch (Exception ex) + { + BasisDebug.LogWarning($"Failed loading disc info from {filePath}: {ex.Message}", BasisDebug.LogTag.Event); + return false; + } } public static bool IsMetaDataOnDisc(string MetaURL, out BasisBEEExtensionMeta info) @@ -301,14 +284,29 @@ public static bool IsMetaDataOnDisc(string MetaURL, out BasisBEEExtensionMeta in return true; } - if (TryLazyLoadDiscInfo(MetaURL, currentPlatform, out BasisBEEExtensionMeta lazyLoadedInfo)) + info = new BasisBEEExtensionMeta(); + return false; + } + } + + public static bool TryLoadMetaDataFromCacheFile(string uniqueVersion, string expectedRemoteUrl, out BasisBEEExtensionMeta info) + { + lock (_discInfoLock) + { + if (string.IsNullOrWhiteSpace(uniqueVersion)) + { + info = new BasisBEEExtensionMeta(); + return false; + } + + string platformAwarePath = BasisIOManagement.GetMetaCacheFilePath(uniqueVersion, BasisIOManagement.GetCurrentCachePlatform()); + if (TryLoadDiscInfoFromFile(platformAwarePath, expectedRemoteUrl, out info)) { - info = lazyLoadedInfo; return true; } - info = new BasisBEEExtensionMeta(); - return false; + string legacyPath = BasisIOManagement.GetLegacyMetaCacheFilePath(uniqueVersion); + return TryLoadDiscInfoFromFile(legacyPath, expectedRemoteUrl, out info); } } @@ -370,8 +368,16 @@ public static async Task EnsureInitializationComplete() private static async Task LoadAllDiscData() { BasisDebug.Log("Loading all disc data...", BasisDebug.LogTag.Event); - string path = BasisIOManagement.GenerateFolderPath(BasisBeeConstants.AssetBundlesFolder); - string[] files = Directory.GetFiles(path, $"*{BasisBeeConstants.BasisMetaExtension}"); + string rootPath = BasisIOManagement.GenerateFolderPath(BasisBeeConstants.AssetBundlesFolder); + string currentPlatformPath = BasisIOManagement.GenerateFolderPath(Path.Combine(BasisBeeConstants.AssetBundlesFolder, BasisIOManagement.GetCurrentCachePlatform())); + + List files = new List(); + files.AddRange(Directory.GetFiles(rootPath, $"*{BasisBeeConstants.BasisMetaExtension}", SearchOption.TopDirectoryOnly)); + + if (!string.Equals(rootPath, currentPlatformPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(currentPlatformPath)) + { + files.AddRange(Directory.GetFiles(currentPlatformPath, $"*{BasisBeeConstants.BasisMetaExtension}", SearchOption.TopDirectoryOnly)); + } List loadTasks = new List(); diff --git a/Basis/Packages/com.basis.bundlemanagement/BasisStorageManagement.cs b/Basis/Packages/com.basis.bundlemanagement/BasisStorageManagement.cs index f49d5d3c7..cea59499f 100644 --- a/Basis/Packages/com.basis.bundlemanagement/BasisStorageManagement.cs +++ b/Basis/Packages/com.basis.bundlemanagement/BasisStorageManagement.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using UnityEngine; @@ -47,11 +48,12 @@ public static long GetTotalCacheSizeBytes() return 0; long total = 0; - foreach (string file in Directory.GetFiles(folderPath)) + DirectoryInfo folderInfo = new DirectoryInfo(folderPath); + foreach (FileInfo file in folderInfo.GetFiles( "*", SearchOption.AllDirectories)) { try { - total += new FileInfo(file).Length; + total += file.Length; } catch (Exception) { @@ -80,12 +82,16 @@ public static List GetAllStoredFiles() remoteUrl = meta.StoredRemote.RemoteBeeFileLocation; string beePath = meta.StoredLocal.DownloadedBeeFileLocation; - if (string.IsNullOrEmpty(beePath)) + if (string.IsNullOrEmpty(beePath) && string.IsNullOrWhiteSpace(meta.UniqueVersion) == false) { beePath = BasisIOManagement.GetBeeCacheFilePath(meta.UniqueVersion, meta.DownloadedPlatform); } - string metaFilePath = BasisIOManagement.GetMetaCacheFilePath(meta.UniqueVersion, meta.DownloadedPlatform); + string metaFilePath = string.Empty; + if (string.IsNullOrWhiteSpace(meta.UniqueVersion) == false) + { + metaFilePath = BasisIOManagement.GetMetaCacheFilePath(meta.UniqueVersion, meta.DownloadedPlatform); + } long fileSize = 0; DateTime lastWrite = DateTime.MinValue; @@ -208,7 +214,7 @@ public static void ClearAllCache() string folderPath = GetCacheFolderPath(); if (Directory.Exists(folderPath)) { - foreach (string file in Directory.GetFiles(folderPath)) + foreach (string file in Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories)) { TryDeleteFile(file); } @@ -279,14 +285,17 @@ private static bool DeleteStoredEntry(string discKey, BasisBEEExtensionMeta meta } string beePath = meta.StoredLocal.DownloadedBeeFileLocation; - if (string.IsNullOrEmpty(beePath)) + if (string.IsNullOrEmpty(beePath) && string.IsNullOrWhiteSpace(meta.UniqueVersion) == false) { beePath = BasisIOManagement.GetBeeCacheFilePath(meta.UniqueVersion, meta.DownloadedPlatform); } TryDeleteFile(beePath); - string metaPath = BasisIOManagement.GetMetaCacheFilePath(meta.UniqueVersion, meta.DownloadedPlatform); - TryDeleteFile(metaPath); + if (string.IsNullOrWhiteSpace(meta.UniqueVersion) == false) + { + string metaPath = BasisIOManagement.GetMetaCacheFilePath(meta.UniqueVersion, meta.DownloadedPlatform); + TryDeleteFile(metaPath); + } BasisDebug.Log($"Deleted stored BEE file: {meta.UniqueVersion} [{meta.DownloadedPlatform}] (source: {meta.StoredRemote.RemoteBeeFileLocation})", BasisDebug.LogTag.Event); return true; diff --git a/Basis/Packages/com.basis.common/BasisDataStore.cs b/Basis/Packages/com.basis.common/BasisDataStore.cs index d5a9b5920..02b70ef6e 100644 --- a/Basis/Packages/com.basis.common/BasisDataStore.cs +++ b/Basis/Packages/com.basis.common/BasisDataStore.cs @@ -7,12 +7,12 @@ namespace Basis.Scripts.Common { public static class BasisDataStore { - public static void SaveAvatar(string avatarName, byte avatarData, string fileNameAndExtension) + public static void SaveAvatar(string avatarName, byte avatarData, string fileNameAndExtension, string cacheFileName = "") { try { string filePath = Path.Combine(Application.persistentDataPath, fileNameAndExtension); - string json = JsonUtility.ToJson(new BasisSavedAvatar(avatarName, avatarData)); + string json = JsonUtility.ToJson(new BasisSavedAvatar(avatarName, avatarData, cacheFileName)); File.WriteAllText(filePath, json); BasisDebug.Log("Avatar saved to " + filePath); } @@ -27,11 +27,13 @@ public class BasisSavedAvatar { public string UniqueID; public byte loadmode; + public string CacheFileName; - public BasisSavedAvatar(string name, byte data) + public BasisSavedAvatar(string name, byte data, string cacheFileName = "") { UniqueID = name; loadmode = data; + CacheFileName = cacheFileName; } } diff --git a/Basis/Packages/com.basis.framework/BasisUI/Menus/Main Menu Providers/SettingsProviderParts/SettingsProviderStorage.cs b/Basis/Packages/com.basis.framework/BasisUI/Menus/Main Menu Providers/SettingsProviderParts/SettingsProviderStorage.cs index a2bef9465..e7baf9413 100644 --- a/Basis/Packages/com.basis.framework/BasisUI/Menus/Main Menu Providers/SettingsProviderParts/SettingsProviderStorage.cs +++ b/Basis/Packages/com.basis.framework/BasisUI/Menus/Main Menu Providers/SettingsProviderParts/SettingsProviderStorage.cs @@ -106,7 +106,9 @@ private static void PopulateStorageData(RectTransform container) foreach (var file in storedFiles) { - string fileName = file.UniqueVersion; + string fileName = string.IsNullOrWhiteSpace(file.UniqueVersion) + ? (string.IsNullOrWhiteSpace(file.LocalPath) ? "Unknown Cache Entry" : System.IO.Path.GetFileName(file.LocalPath)) + : file.UniqueVersion; string size = BasisStorageManagement.FormatBytes(file.FileSizeBytes); string loadedStatus = file.IsLoadedInMemory ? " [IN USE]" : ""; string remoteUrl = file.RemoteUrl; diff --git a/Basis/Packages/com.basis.framework/Players/Local/BasisLocalPlayer.cs b/Basis/Packages/com.basis.framework/Players/Local/BasisLocalPlayer.cs index 8c9ff5517..54fa4ba50 100644 --- a/Basis/Packages/com.basis.framework/Players/Local/BasisLocalPlayer.cs +++ b/Basis/Packages/com.basis.framework/Players/Local/BasisLocalPlayer.cs @@ -253,7 +253,21 @@ public async Task LocalInitialize() /// Metadata pointing to the last persisted avatar selection. public async Task LoadInitialAvatar(BasisDataStore.BasisSavedAvatar LastUsedAvatar) { - if (BasisLoadHandler.IsMetaDataOnDisc(LastUsedAvatar.UniqueID, out BasisBEEExtensionMeta info)) + bool hasCachedMeta = false; + BasisBEEExtensionMeta info = null; + + if (!string.IsNullOrWhiteSpace(LastUsedAvatar.CacheFileName)) + { + hasCachedMeta = BasisLoadHandler.TryLoadMetaDataFromCacheFile(LastUsedAvatar.CacheFileName, LastUsedAvatar.UniqueID, out info); + } + + if (!hasCachedMeta) + { + await BasisLoadHandler.EnsureInitializationComplete(); + hasCachedMeta = BasisLoadHandler.IsMetaDataOnDisc(LastUsedAvatar.UniqueID, out info); + } + + if (hasCachedMeta) { await BasisDataStoreItemKeys.LoadKeys(); ItemKey[] activeKeys = BasisDataStoreItemKeys.DisplayKeys(); @@ -339,7 +353,7 @@ public async Task CreateAvatar(byte LoadMode, BasisLoadableBundle BasisLoadableB { await BasisAvatarFactory.LoadAvatarLocal(this, LoadMode, BasisLoadableBundle, this.transform.position, Quaternion.identity); OnLocalAvatarChanged?.Invoke(); - BasisDataStore.SaveAvatar(BasisLoadableBundle.BasisRemoteBundleEncrypted.RemoteBeeFileLocation, LoadMode, LoadFileNameAndExtension); + BasisDataStore.SaveAvatar(BasisLoadableBundle.BasisRemoteBundleEncrypted.RemoteBeeFileLocation, LoadMode, LoadFileNameAndExtension, BasisLoadableBundle.BasisBundleConnector?.UniqueVersion); } ///