예제 #1
0
        public static string GetCustomLevelHash(CustomBeatmapLevel level)
        {
            if (GetCachedSongData(level.customLevelPath, out var directoryHash, out var songHash))
            {
                return(songHash);
            }

            byte[] combinedBytes = new byte[0];
            combinedBytes = combinedBytes.Concat(File.ReadAllBytes(level.customLevelPath + '/' + "info.dat")).ToArray();
            for (var i = 0; i < level.standardLevelInfoSaveData.difficultyBeatmapSets.Length; i++)
            {
                for (var i2 = 0; i2 < level.standardLevelInfoSaveData.difficultyBeatmapSets[i].difficultyBeatmaps.Length; i2++)
                {
                    if (File.Exists(level.customLevelPath + '/' + level.standardLevelInfoSaveData.difficultyBeatmapSets[i].difficultyBeatmaps[i2].beatmapFilename))
                    {
                        combinedBytes = combinedBytes
                                        .Concat(File.ReadAllBytes(level.customLevelPath + '/' + level.standardLevelInfoSaveData.difficultyBeatmapSets[i].difficultyBeatmaps[i2].beatmapFilename)).ToArray();
                    }
                }
            }

            string hash = CreateSha1FromBytes(combinedBytes.ToArray());

            cachedSongHashData[level.customLevelPath] = new SongHashData(directoryHash, hash);
            return(hash);
        }
예제 #2
0
        private async Task <CustomBeatmapLevel> LoadCustomBeatmapLevelAsync(CustomPreviewBeatmapLevel level, CancellationToken token)
        {
            CustomBeatmapLevel customLevel = new CustomBeatmapLevel(level, null, null);
            BeatmapLevelData   beatmapData = await _customLevelLoader.LoadBeatmapLevelDataAsync(level.customLevelPath, customLevel, level.standardLevelInfoSaveData, token).ConfigureAwait(false);

            customLevel.SetBeatmapLevelData(beatmapData);

            return(customLevel);
        }
예제 #3
0
        private void ConfirmDeleteButtonPressed(CustomBeatmapLevel level)
        {
            // scrolling back to the previous position is done by SongListUIAdditions
            // just need to deal with setting up the current pack here
            var currentPack = LevelSelectionNavigationController.GetPrivateField <IBeatmapLevelPack>("_levelPack", typeof(LevelSelectionNavigationController));

            // if the current list of levels does not belong to a level pack, just provide the same levels minus the deleted song
            if (currentPack == null)
            {
                IPreviewBeatmapLevel[] levels            = _levelCollectionTableView.GetPrivateField <IPreviewBeatmapLevel[]>("_previewBeatmapLevels", typeof(LevelCollectionTableView));
                BeatmapLevelCollection replacementLevels = new BeatmapLevelCollection(levels.Where(x => x.levelID != level.levelID).ToArray());

                Loader.Instance.DeleteSong(level.customLevelPath);

                LevelSelectionNavigationController.SetData(
                    replacementLevels,
                    LevelSelectionNavigationController.GetPrivateField <bool>("_showPlayerStatsInDetailView", typeof(LevelSelectionNavigationController)),
                    LevelSelectionNavigationController.GetPrivateField <bool>("_showPracticeButtonInDetailView", typeof(LevelSelectionNavigationController)),
                    null);
            }
            // check if the current level pack is this mod's filtered/sorted level pack
            // if it is, just remove the song from the level pack and show it again
            else if (currentPack.packID == FilteredLevelsLevelPack.PackID || currentPack.packID.Contains(SortedLevelsLevelPack.PackIDSuffix))
            {
                // remove the song from the pack
                var replacementPack = new BeatmapLevelPack(
                    currentPack.packID,
                    currentPack.packName,
                    currentPack.shortPackName,
                    currentPack.coverImage,
                    new BeatmapLevelCollection(currentPack.beatmapLevelCollection.beatmapLevels.Where(x => x.levelID != level.levelID).ToArray()));

                try
                {
                    _isDeletingSongInModOwnedLevelPack = true;
                    Loader.Instance.DeleteSong(level.customLevelPath);
                }
                finally
                {
                    _isDeletingSongInModOwnedLevelPack = false;
                }

                LevelSelectionNavigationController.SetData(
                    replacementPack,
                    true,
                    LevelSelectionNavigationController.GetPrivateField <bool>("_showPlayerStatsInDetailView", typeof(LevelSelectionNavigationController)),
                    LevelSelectionNavigationController.GetPrivateField <bool>("_showPracticeButtonInDetailView", typeof(LevelSelectionNavigationController)));
            }
            // if the current level pack is not from this mod, just delete
            // SongCore should automatically reload the pack
            else
            {
                Loader.Instance.DeleteSong(level.customLevelPath);
            }
        }
예제 #4
0
        private async Task <Tuple <int, BeatmapDetails> > GetCustomBeatmapDetailsAsync(CustomPreviewBeatmapLevel level, int index)
        {
            try
            {
                CustomBeatmapLevel customLevel = await LoadCustomBeatmapLevelAsync(level, _loadingTokenSource.Token);

                var details = new BeatmapDetails(customLevel);
                _cache[GetLevelID(level)] = details;

                return(new Tuple <int, BeatmapDetails>(index, details));
            }
            catch (OperationCanceledException) { }

            return(new Tuple <int, BeatmapDetails>(index, null));
        }
        /// <summary>
        /// Loads a single custom beatmap level.
        /// </summary>
        /// <param name="level">The custom preview beatmap for which you want to load the IBeatmapLevel for.</param>
        /// <param name="onFinish">The function that is called when the IBeatmapLevel is retrieved.</param>
        /// <returns>An awaitable Task.</returns>
        public async Task LoadSingleBeatmapAsync(CustomPreviewBeatmapLevel level, Action <IBeatmapLevel> onFinish)
        {
            CancellationTokenSource tokenSource = new CancellationTokenSource(TimeoutDelay);
            CustomBeatmapLevel      customLevel = new CustomBeatmapLevel(CreateLevelCopyWithReplacedMediaLoader(level, MediaLoader), null, null);

            try
            {
                BeatmapLevelData beatmapData = await LevelLoader.LoadBeatmapLevelDataAsync(level.customLevelPath, customLevel, level.standardLevelInfoSaveData, tokenSource.Token);

                if (beatmapData != null)
                {
                    customLevel.SetBeatmapLevelData(beatmapData);

                    string levelID = GetSimplifiedLevelID(customLevel);
                    if (!_cache.ContainsKey(levelID) && !IsCaching)
                    {
                        _cache[GetSimplifiedLevelID(customLevel)] = new BeatmapDetails(customLevel);
                    }

                    try
                    {
                        onFinish?.Invoke(customLevel);
                    }
                    catch (Exception e)
                    {
                        Logger.log.Warn("Unexpected exception occurred in delegate after loading beatmap");
                        Logger.log.Debug(e);
                    }
                }
                else
                {
                    Logger.log.Debug($"Unable to load beatmap level data for '{level.songName}' (no data returned)");
                }
            }
            catch (OperationCanceledException)
            {
                Logger.log.Debug($"Unable to load beatmap level data for '{level.songName}' (load task timed out)");
            }

            tokenSource.Dispose();
        }
예제 #6
0
        private async Task CacheCustomBeatmapDetailsAsync(CustomPreviewBeatmapLevel level)
        {
            CustomBeatmapLevel customLevel = await LoadCustomBeatmapLevelAsync(level, _cachingTokenSource.Token).ConfigureAwait(false);

            _cache[GetLevelID(level)] = new BeatmapDetails(customLevel);
        }
예제 #7
0
 private static void Postfix(CustomBeatmapLevel __instance, CustomPreviewBeatmapLevel customPreviewBeatmapLevel)
 {
     __instance.SetField <CustomPreviewBeatmapLevel, float>("_songDuration", customPreviewBeatmapLevel.songDuration);
 }