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); }
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); }
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); } }
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(); }
private async Task CacheCustomBeatmapDetailsAsync(CustomPreviewBeatmapLevel level) { CustomBeatmapLevel customLevel = await LoadCustomBeatmapLevelAsync(level, _cachingTokenSource.Token).ConfigureAwait(false); _cache[GetLevelID(level)] = new BeatmapDetails(customLevel); }
private static void Postfix(CustomBeatmapLevel __instance, CustomPreviewBeatmapLevel customPreviewBeatmapLevel) { __instance.SetField <CustomPreviewBeatmapLevel, float>("_songDuration", customPreviewBeatmapLevel.songDuration); }