Exemplo n.º 1
0
            private IEnumerator PopulateCacheFromFileCoroutine()
            {
                var coroutine = BeatmapDetailsCache.GetBeatmapDetailsFromCacheCoroutine(BeatmapDetailsLoader.CachedBeatmapDetailsFilePath);

                List <BeatmapDetails> loadedCache = null;

                while (coroutine.MoveNext())
                {
                    loadedCache = coroutine.Current;

                    if (loadedCache == null)
                    {
                        yield return(null);
                    }
                }

                if (loadedCache != null)
                {
                    if (loadedCache.Count > 0)
                    {
                        Logger.log.Info($"Retrieved {loadedCache.Count} cached beatmap details from file");
                    }

                    foreach (var detail in loadedCache)
                    {
                        if (!BeatmapDetailsLoader._cache.ContainsKey(detail.LevelID))
                        {
                            BeatmapDetailsLoader._cache.Add(detail.LevelID, detail);
                        }
                    }
                }
            }
Exemplo n.º 2
0
        public async Task PopulateCacheFromFile()
        {
            var detailsList = await BeatmapDetailsCache.GetBeatmapDetailsFromCacheAsync(CachedBeatmapDetailsFilePath);

            foreach (var detail in detailsList)
            {
                _cache.TryAdd(detail.LevelID, detail);
            }
        }
Exemplo n.º 3
0
        public static IEnumerator <List <BeatmapDetails> > GetBeatmapDetailsFromCacheCoroutine(string path)
        {
            if (!File.Exists(path))
            {
                Logger.log.Notice($"Cache file could not be found in the path: '{path}'");
                yield break;
            }

            string fileContents = null;
            IEnumerator <string> cacheLoader = UnityMediaLoader.LoadTextCoroutine(path);

            while (cacheLoader.MoveNext())
            {
                fileContents = cacheLoader.Current;

                if (fileContents == null)
                {
                    yield return(null);
                }
            }

            if (string.IsNullOrEmpty(fileContents))
            {
                Logger.log.Warn("Beatmap details cache is empty");
                yield break;
            }

            BeatmapDetailsCache cache = null;

            try
            {
                cache = JsonConvert.DeserializeObject <BeatmapDetailsCache>(fileContents);
            }
            catch (JsonSerializationException)
            {
                Logger.log.Warn("Unable to deserialize cache file. Could be an older bersion of the cache file (will be replaced after the in-memory cache is rebuilt)");
                yield break;
            }
            catch (Exception e)
            {
                Logger.log.Warn("Unexpected exception occurred when trying to deserialize beatmap details cache");
                Logger.log.Debug(e);
                yield break;
            }

            if (cache.Version < CURRENT_CACHE_VERSION)
            {
                Logger.log.Warn("Beatmap details cache is outdated. Forcing the cache to be rebuilt");
            }
            else
            {
                Logger.log.Info("Successfully loaded details cache from storage");
                yield return(cache.Cache);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Save the cached BeatmapDetails objects to a JSON file located at CachedBeatmapDetailsFilePath.
        /// </summary>
        public void SaveCacheToFile()
        {
            List <BeatmapDetails> cache = _cache.Values.ToList();

            // remove WIP levels from cache (don't save them, since they're likely to change often and
            // if we don't delete any entries in the cache, it may cause the cache to balloon in size)
            var wipLevels = Loader.CustomWIPLevels.Values.Select(x => GetCustomLevelIDWithoutDirectory(x.levelID));

            cache = cache.Where(c => !wipLevels.Any(wip => wip == c.LevelID)).ToList();

            // remove beatmaps that are not loaded
            var customLevels = Loader.CustomLevels.Values.Select(x => GetCustomLevelIDWithoutDirectory(x.levelID));

            cache = cache.Where(c => customLevels.Any(level => level == c.LevelID)).ToList();

            BeatmapDetailsCache.SaveBeatmapDetailsToCache(CachedBeatmapDetailsFilePath, cache);
        }
        /// <summary>
        /// Save the cached BeatmapDetails objects to a JSON file located at CachedBeatmapDetailsFilePath.
        /// </summary>
        public void SaveCacheToFile()
        {
            if (PluginConfig.DisableFilters)
            {
                return;
            }

            List <BeatmapDetails> cache = _cache.Values.ToList();

            // remove WIP levels from cache (don't save them, since they're likely to change often and
            // if we don't delete any entries in the cache, it may cause the cache to balloon in size)
            var wipLevels = Loader.CustomWIPLevels.Values.Select(x => GetCustomLevelIDWithoutDirectory(x.levelID));

            cache = cache.Where(c => !wipLevels.Any(wip => wip == c.LevelID)).ToList();

            // remove beatmaps that are not loaded
            var customLevels = Loader.CustomLevels.Values.Select(x => GetCustomLevelIDWithoutDirectory(x.levelID));

            cache = cache.Where(c => customLevels.Any(level => level == c.LevelID)).ToList();

            // repeat the above checks for user-added folders
            foreach (var folder in Loader.SeperateSongFolders)
            {
                var levels = folder.Levels.Values.Select(x => GetCustomLevelIDWithoutDirectory(x.levelID));

                if (folder.SongFolderEntry.WIP)
                {
                    cache = cache.Where(c => !levels.Any(wip => wip == c.LevelID)).ToList();
                }
                else
                {
                    cache = cache.Where(c => levels.Any(level => level == c.LevelID)).ToList();
                }
            }

            if (cache.Count > 0)
            {
                BeatmapDetailsCache.SaveBeatmapDetailsToCache(CachedBeatmapDetailsFilePath, cache);
            }
        }
Exemplo n.º 6
0
            private void CachingThread()
            {
                try
                {
                    var sw = Stopwatch.StartNew();

                    // load cache from file
                    List <BeatmapDetails> loadedCache = BeatmapDetailsCache.GetBeatmapDetailsFromCache(BeatmapDetailsLoader.CachedBeatmapDetailsFilePath);
                    if (loadedCache != null)
                    {
                        if (loadedCache.Count > 0)
                        {
                            Logger.log.Info($"Retrieved {loadedCache.Count} cached beatmap details from file");
                        }

                        foreach (var detail in loadedCache)
                        {
                            if (!BeatmapDetailsLoader._cache.ContainsKey(detail.LevelID))
                            {
                                BeatmapDetailsLoader._cache.Add(detail.LevelID, detail);
                            }
                        }
                    }

                    List <IEnumerator <BeatmapDetails> > taskList           = new List <IEnumerator <BeatmapDetails> >(WorkChunkSize);
                    List <IPreviewBeatmapLevel>          allCustomLevels    = BeatmapDetailsLoader.GetAllCustomLevels();
                    List <SongDataCoreDataStatus>        sdcErrorStatusList = new List <SongDataCoreDataStatus>(allCustomLevels.Count);
                    int  index      = 0;
                    int  errorCount = 0;
                    long elapsed    = 0;
                    while (index < allCustomLevels.Count)
                    {
                        if (sw.ElapsedMilliseconds > 30000 + elapsed)
                        {
                            elapsed = sw.ElapsedMilliseconds;
                            Logger.log.Debug($"Caching thread has finished caching {index} beatmaps out of {allCustomLevels.Count} ({elapsed} ms elapsed)");
                        }

                        _manualResetEvent.WaitOne();
                        if (_isOperationCancelled)
                        {
                            return;
                        }

                        for (int i = 0; i < WorkChunkSize && index < allCustomLevels.Count; ++index)
                        {
                            IPreviewBeatmapLevel level = allCustomLevels[index];
                            string         levelID     = GetSimplifiedLevelID(level);
                            BeatmapDetails beatmapDetails;

                            if (BeatmapDetailsLoader._cache.ContainsKey(levelID) && BeatmapDetailsLoader._cache[levelID].SongDuration > 0.01f)
                            {
                                continue;
                            }

                            SongDataCoreDataStatus status = SongDataCoreTweaks.GetBeatmapDetails(level as CustomPreviewBeatmapLevel, out beatmapDetails);

                            if (status == SongDataCoreDataStatus.Success)
                            {
                                if (beatmapDetails.DifficultyBeatmapSets.Any(set => set.DifficultyBeatmaps.Any(diff => diff.NoteJumpMovementSpeed == 0)))
                                {
                                    Logger.log.Debug($"BeatmapDetails object generated for '{beatmapDetails.SongName}' from BeatSaver data has some incomplete fields. " +
                                                     "Discarding and generating BeatmapDetails object from locally stored information instead");

                                    taskList.Add(BeatmapDetails.CreateBeatmapDetailsFromFilesCoroutine(level as CustomPreviewBeatmapLevel));
                                    ++i;
                                }
                                else
                                {
                                    BeatmapDetailsLoader._cache[levelID] = beatmapDetails;
                                }
                            }
                            else
                            {
                                if (SongDataCoreTweaks.IsModAvailable)
                                {
                                    sdcErrorStatusList.Add(status);
                                }

                                taskList.Add(BeatmapDetails.CreateBeatmapDetailsFromFilesCoroutine(level as CustomPreviewBeatmapLevel));
                                ++i;
                            }
                        }

                        while (taskList.Any())
                        {
                            _manualResetEvent.WaitOne();
                            if (_isOperationCancelled)
                            {
                                return;
                            }

                            for (int i = 0; i < taskList.Count; ++i)
                            {
                                IEnumerator <BeatmapDetails> loadCoroutine = taskList[i];

                                if (loadCoroutine.MoveNext())
                                {
                                    BeatmapDetails beatmapDetails = loadCoroutine.Current;
                                    if (beatmapDetails != null)
                                    {
                                        BeatmapDetailsLoader._cache[beatmapDetails.LevelID] = beatmapDetails;
                                        taskList.Remove(loadCoroutine);
                                        --i;
                                    }
                                }
                                else
                                {
                                    ++errorCount;
                                    taskList.Remove(loadCoroutine);
                                    --i;
                                }
                            }
                        }
                    }

                    sw.Stop();
                    Logger.log.Info($"Finished caching the details of {allCustomLevels.Count} beatmaps (took {sw.ElapsedMilliseconds / 1000f} seconds)");

                    if (errorCount > 0)
                    {
                        Logger.log.Warn($"Unable to cache the beatmap details for {errorCount} songs");
                    }

                    if (sdcErrorStatusList.Count > 0)
                    {
                        // NOTE: this will need to be updated if i ever add more error status markers
                        Logger.log.Debug($"Unable to retrieve some data from SongDataCore: (" +
                                         $"NoData = {sdcErrorStatusList.Count(x => x == SongDataCoreDataStatus.NoData)}, " +
                                         $"InvalidBPM = {sdcErrorStatusList.Count(x => x == SongDataCoreDataStatus.InvalidBPM)}, " +
                                         $"InvalidDuration = {sdcErrorStatusList.Count(x => x == SongDataCoreDataStatus.InvalidDuration)}, " +
                                         $"InvalidCharacteristicString = {sdcErrorStatusList.Count(x => x == SongDataCoreDataStatus.InvalidCharacteristicString)}, " +
                                         $"InvalidDifficultyString = {sdcErrorStatusList.Count(x => x == SongDataCoreDataStatus.InvalidDifficultyString)}, " +
                                         $"ExceptionThrown = {sdcErrorStatusList.Count(x => x == SongDataCoreDataStatus.ExceptionThrown)})");
                    }

                    BeatmapDetailsLoader.instance.SaveCacheToFile();

                    HMMainThreadDispatcher.instance.Enqueue(delegate()
                    {
                        _thread = null;
                        _manualResetEvent.Dispose();
                        _manualResetEvent = null;

                        CachingFinished?.Invoke();
                    });
                }
                catch (Exception e)
                {
                    Logger.log.Warn("Unexpected exception occurred in caching thread");
                    Logger.log.Debug(e);
                }
            }
Exemplo n.º 7
0
        public static void SaveBeatmapDetailsToCache(string path, List <BeatmapDetails> beatmapDetailsList)
        {
            var cache = new BeatmapDetailsCache(beatmapDetailsList);

            File.WriteAllText(path, JsonConvert.SerializeObject(cache));
        }