internal override void PerformOp(OpContext context) { if (string.IsNullOrEmpty(SongID)) { throw new InvalidOperationException("SongID must be provided."); } if (!context.Cache.SongCache.ContainsKey(SongID)) { throw new InvalidOperationException("SongID does not exist."); } OpCommon.DeleteSong(context, SongID); }
public static void DeletePlaylist(OpContext context, string playlistID, bool deleteSongsOnPlaylist) { var playlist = context.Cache.PlaylistCache[playlistID]; if (deleteSongsOnPlaylist) { try { foreach (var song in playlist.Songs.ToList()) { try { OpCommon.DeleteSong(context, song.Key); } catch (Exception ex) { Log.LogErr($"Exception trying to delete song id {song.Key} while deleting playlist id {playlist.Playlist.PackID}, will be unlinked in cache. This may leave unused data in the assets.", ex); try { context.Cache.SongCache.Remove(song.Value.Song.LevelID); playlist.Songs.Remove(song.Value.Song.LevelID); } catch (Exception ex2) { Log.LogErr($"Exception cleaning up cache for song id {song.Key} in playlist if {playlist.Playlist.PackID} while recovering from a failed delete.", ex2); } } } } catch (Exception ex) { //really this shouldn't ever get hit anymore. Probably can remove it. Log.LogErr($"Deleting songs on playlist ID {playlist?.Playlist?.PackID} failed! Attempting to recover by removing links to songs, although this may leave extra stuff in assets!"); try { var bmCol = playlist?.Playlist?.BeatmapLevelCollection?.Object?.BeatmapLevels?.ToList(); if (bmCol != null) { bmCol.ForEach(x => { playlist.Playlist.BeatmapLevelCollection.Object.BeatmapLevels.Remove(x); x.Dispose(); }); } } catch (Exception ex2) { Log.LogErr($"Failed to recover by removing song pointers while deleting playlist {playlist?.Playlist?.PackID}! This will definitely leave stuff in assets.", ex2); } } playlist.Songs.Clear(); } //this should be done in song delete already //playlist.Playlist.BeatmapLevelCollection.Object.BeatmapLevels.ForEach(x => { x.Target.ParentFile.DeleteObject(x.Object); x.Dispose(); }); var mlp = context.Engine.GetMainLevelPack(); var aop = context.Engine.GetAlwaysOwnedModel(); var mlpptr = mlp.BeatmapLevelPacks.FirstOrDefault(x => x.Object.PackID == playlist.Playlist.PackID); var aopptr = aop.AlwaysOwnedPacks.FirstOrDefault(x => x.Object.PackID == playlist.Playlist.PackID); if (mlpptr != null) { mlp.BeatmapLevelPacks.Remove(mlpptr); mlpptr.Dispose(); } else { Log.LogErr($"The playlist id {playlist.Playlist.PackID} didn't exist in the main level packs"); } if (aopptr != null) { aop.AlwaysOwnedPacks.Remove(aopptr); aopptr.Dispose(); } else { Log.LogErr($"The playlist id {playlist.Playlist.PackID} didn't exist in the always owned level packs"); } //don't delete built in packs assets, just unlink them if (!BSConst.KnownLevelPackIDs.Contains(playlist.Playlist.PackID)) { var plParent = playlist.Playlist.ObjectInfo.ParentFile; plParent.DeleteObject(playlist.Playlist.CoverImage.Object.RenderData.Texture.Object); playlist.Playlist.CoverImage.Object.RenderData.Texture.Dispose(); plParent.DeleteObject(playlist.Playlist.CoverImage.Object); plParent.DeleteObject(playlist.Playlist); playlist.Playlist.CoverImage.Dispose(); } context.Cache.PlaylistCache.Remove(playlistID); }
internal override void PerformOp(OpContext context) { if (string.IsNullOrEmpty(Song.SongID)) { throw new InvalidOperationException("SongID must be set on the song!"); } if (string.IsNullOrEmpty(Song.CustomSongPath)) { throw new InvalidOperationException("CustomSongPath must be set on the song!"); } if (!context.Cache.PlaylistCache.ContainsKey(PlaylistID)) { throw new KeyNotFoundException($"PlaylistID {PlaylistID} not found in the cache!"); } bool exists = context.Cache.SongCache.ContainsKey(Song.SongID); if (exists && !OverwriteIfExists) { throw new AddSongException(AddSongFailType.SongExists, $"SongID {Song.SongID} already exists!"); } if (exists && OverwriteIfExists) { OpCommon.DeleteSong(context, Song.SongID); } if (context.Cache.SongCache.ContainsKey(Song.SongID)) { throw new AddSongException(AddSongFailType.SongExists, $"SongID {Song.SongID} already exists, even though it should have been deleted to be replaced!"); } BeatmapLevelDataObject level = null; try { var songsAssetFile = context.Engine.GetSongsAssetsFile(); CustomLevelLoader loader = new CustomLevelLoader(songsAssetFile, context.Config); var deser = loader.DeserializeFromJson(Song.CustomSongPath, Song.SongID); level = loader.LoadSongToAsset(deser, Song.CustomSongPath, true); } catch (Exception ex) { throw new Exception($"Exception loading custom song folder '{Song.CustomSongPath}' for SongID {Song.SongID}", ex); } if (level == null) { throw new AddSongException(AddSongFailType.InvalidFormat, $"Song at folder '{Song.CustomSongPath}' for SongID {Song.SongID} failed to load"); } Song.LevelData = level; Song.LevelAuthorName = level.LevelAuthorName; Song.SongAuthorName = level.SongAuthorName; Song.SongName = level.SongName; Song.SongSubName = level.SongSubName; var playlist = context.Cache.PlaylistCache[PlaylistID]; playlist.Playlist.BeatmapLevelCollection.Object.BeatmapLevels.Add(Song.LevelData.PtrFrom(playlist.Playlist.BeatmapLevelCollection.Object)); playlist.Songs.Add(Song.SongID, new OrderedSong() { Song = Song.LevelData, Order = playlist.Songs.Count }); context.Cache.SongCache.Add(Song.SongID, new SongAndPlaylist() { Playlist = playlist.Playlist, Song = Song.LevelData }); var qfos = context.Engine.QueuedFileOperations.Where(x => x.Tag == Song.SongID && x.Type == QueuedFileOperationType.DeleteFolder || x.Type == QueuedFileOperationType.DeleteFile).ToList(); foreach (var q in qfos) { context.Engine.QueuedFileOperations.Remove(q); } }