Exemplo n.º 1
0
        public static void Init()
        {
            _customLevelLoader = Resources.FindObjectsOfTypeAll <CustomLevelLoader>().FirstOrDefault();
            beatmapCharacteristicCollection = _customLevelLoader.GetField <BeatmapCharacteristicCollectionSO>("_beatmapCharacteristicCollection");

            Texture2D defaultCoverTex = Texture2D.blackTexture;

            defaultCoverImage = Sprite.Create(defaultCoverTex, new Rect(0f, 0f,
                                                                        defaultCoverTex.width, defaultCoverTex.height), new Vector2(0.5f, 0.5f));
            cachedMediaAsyncLoaderSO = _customLevelLoader.GetField <CachedMediaAsyncLoader>("_cachedMediaAsyncLoaderSO");
        }
Exemplo n.º 2
0
        private static BeatmapCharacteristicCollectionSO GetDefaultGameModes()
        {
            CustomLevelLoader customLevelLoader = UnityEngine.Object.FindObjectOfType <CustomLevelLoader>();

            if (customLevelLoader == null)
            {
                Plugin.Log.Info("customLevelLoader is null");
                return(null);
            }
            BeatmapCharacteristicCollectionSO defaultGameModes = FieldHelper.Get <BeatmapCharacteristicCollectionSO>(customLevelLoader, "_beatmapCharacteristicCollection");

            if (defaultGameModes == null)
            {
                Plugin.Log.Warn("defaultGameModes is null");
            }
            return(defaultGameModes);
        }
Exemplo n.º 3
0
        //private bool SaberExists(AssetsManager manager, string saberID)
        //{
        //    var file11 = manager.GetAssetsFile(BSConst.KnownFiles.File11);
        //    return file11.FindAsset<GameObject>(x => x.Object.Name == $"{saberID}Saber") != null;
        //}

        //private string GetCurrentSaberID(AssetsManager manager)
        //{
        //    var saberChild = GetSaberObjectParentTransform(manager)?.GameObject?.Object;
        //    if (saberChild == null)
        //        throw new Exception("Couldn't find child saber game object of transform.");
        //    return saberChild.Name.Substring(0, saberChild.Name.Length - 5);
        //}

        //private Transform GetSaberObjectParentTransform(AssetsManager manager)
        //{
        //    var file11 = manager.GetAssetsFile(BSConst.KnownFiles.File11);
        //    var basicSaberModel = file11.FindAsset<GameObject>(x => x.Object.Name == "BasicSaberModel");

        //    if (basicSaberModel == null)
        //        throw new Exception("Couldn't find BasicSaberModel!");

        //    var transform = basicSaberModel.Object.Components.FirstOrDefault(x => x.Object is Transform)?.Object as Transform;
        //    if (transform == null)
        //        throw new Exception("Couldn't find Transform on BasicSaberModel!");

        //    var saberParent = (transform.Children.FirstOrDefault(x => x.Object is Transform
        //            && ((x.Object as Transform).GameObject?.Object?.Name?.EndsWith("Saber") ?? false)).Object as Transform);
        //    if (saberParent == null)
        //        throw new Exception("Could not find child transform of BasicSaberModel!");
        //    return saberParent;
        //}

        //private void SwapToSaberID(AssetsManager manager, string saberID)
        //{
        //    var file11 = manager.GetAssetsFile(BSConst.KnownFiles.File11);

        //    var newSaber = file11.FindAsset<GameObject>(x => x.Object.Name == $"{saberID}Saber")?.Object;
        //    if (newSaber == null)
        //        throw new Exception($"Saber with ID {saberID} does not exist!");

        //    var newSaberTransform = newSaber.Components.FirstOrDefault(x => x.Object is Transform).Object as Transform;
        //    if (newSaberTransform == null)
        //        throw new Exception($"Saber with ID {saberID} is missing its parent transform!");

        //    var basicSaberModel = file11.FindAsset<GameObject>(x => x.Object.Name == "BasicSaberModel");

        //    if (basicSaberModel == null)
        //        throw new Exception("Couldn't find BasicSaberModel!");

        //    var transform = basicSaberModel.Object.Components.FirstOrDefault(x => x.Object is Transform)?.Object as Transform;
        //    if (transform == null)
        //        throw new Exception("Couldn't find Transform on BasicSaberModel!");

        //    var saberChild = transform.Children.FirstOrDefault(x => x.Object.GameObject?.Object?.Name?.EndsWith("Saber")??false);
        //    if (saberChild == null)
        //        throw new Exception("Couldn't find a game object on the BasicSaberModel Transform that ended with -Saber!");
        //    int saberIndex = transform.Children.IndexOf(saberChild);
        //    saberChild.Object.Father = null;
        //    transform.Children[saberIndex] = newSaberTransform.PtrFrom(transform) as ISmartPtr<Transform>;
        //    newSaberTransform.Father = transform.PtrFrom(newSaberTransform);
        //}
        #endregion

        private BeatSaberQuestomConfig GetConfig()
        {
            lock (this)
            {
                BeatSaberQuestomConfig config = new BeatSaberQuestomConfig();
                var mainPack             = GetMainLevelPack();
                CustomLevelLoader loader = new CustomLevelLoader(GetSongsAssetsFile(), _config);
                foreach (var packPtr in mainPack.BeatmapLevelPacks)
                {
                    var pack = packPtr.Target.Object;
                    if (HideOriginalPlaylists && BSConst.KnownLevelPackIDs.Contains(pack.PackID))
                    {
                        continue;
                    }

                    var packModel = new BeatSaberPlaylist()
                    {
                        PlaylistName = pack.PackName, PlaylistID = pack.PackID, LevelPackObject = pack
                    };
                    var collection = pack.BeatmapLevelCollection.Object;

                    foreach (var songPtr in collection.BeatmapLevels)
                    {
                        var songObj   = songPtr.Object;
                        var songModel = new BeatSaberSong()
                        {
                            LevelAuthorName = songObj.LevelAuthorName,
                            SongID          = songObj.LevelID,
                            SongAuthorName  = songObj.SongAuthorName,
                            SongName        = songObj.SongName,
                            SongSubName     = songObj.SongSubName,
                            LevelData       = songObj
                        };
                        songModel.CoverArtFilename = loader.GetCoverImageFilename(songObj);
                        packModel.SongList.Add(songModel);
                    }
                    config.Playlists.Add(packModel);
                }
                return(config);
            }
        }
Exemplo n.º 4
0
        internal void MenuLoaded()
        {
            if (AreSongsLoading)
            {
                //Scene changing while songs are loading. Since we are using a separate thread while loading, this is bad and could cause a crash.
                //So we have to stop loading.
                if (_loadingTask != null)
                {
                    _loadingTask.Cancel();
                    _loadingCancelled = true;
                    AreSongsLoading   = false;
                    LoadingProgress   = 0;
                    StopAllCoroutines();
                    _progressBar.ShowMessage("Loading cancelled\n<size=80%>Press Ctrl+R to refresh</size>");
                    Logging.Log("Loading was cancelled by player since they loaded another scene.");
                }
            }
            BS_Utils.Gameplay.Gamemode.Init();
            if (_customLevelLoader == null)
            {
                _customLevelLoader = Resources.FindObjectsOfTypeAll <CustomLevelLoader>().FirstOrDefault();
                if (_customLevelLoader)
                {
                    Texture2D defaultCoverTex = _customLevelLoader.GetField <Texture2D>("_defaultPackCoverTexture2D");
                    defaultCoverImage = Sprite.Create(defaultCoverTex, new Rect(0f, 0f,
                                                                                defaultCoverTex.width, defaultCoverTex.height), new Vector2(0.5f, 0.5f));

                    cachedMediaAsyncLoaderSO        = _customLevelLoader.GetField <CachedMediaAsyncLoader>("_cachedMediaAsyncLoaderSO");
                    beatmapCharacteristicCollection = _customLevelLoader.GetField <BeatmapCharacteristicCollectionSO>("_beatmapCharacteristicCollection");
                }
                else
                {
                    Texture2D defaultCoverTex = Texture2D.blackTexture;
                    defaultCoverImage = Sprite.Create(defaultCoverTex, new Rect(0f, 0f,
                                                                                defaultCoverTex.width, defaultCoverTex.height), new Vector2(0.5f, 0.5f));
                }
            }
        }
Exemplo n.º 5
0
        private IEnumerator DelayedSetup()
        {
            //Slight delay before grabbing needed objects
            yield return(new WaitForSeconds(0.1f));

            _timeSync                  = Resources.FindObjectsOfTypeAll <AudioTimeSyncController>().LastOrDefault(x => x.isActiveAndEnabled);
            _songAudio                 = _timeSync.GetField <AudioSource>("_audioSource");
            _levelLoader               = Resources.FindObjectsOfTypeAll <CustomLevelLoader>().First();
            _spawnController           = Resources.FindObjectsOfTypeAll <BeatmapObjectSpawnController>().LastOrDefault(x => x.isActiveAndEnabled);
            _originalSpawnMovementData = _spawnController.GetField <BeatmapObjectSpawnMovementData>("_beatmapObjectSpawnMovementData");
            _pauseController           = Resources.FindObjectsOfTypeAll <PauseController>().LastOrDefault(x => x.isActiveAndEnabled);
            _callbackController        = Resources.FindObjectsOfTypeAll <BeatmapObjectCallbackController>().LastOrDefault(x => x.isActiveAndEnabled);
            _seManager                 = Resources.FindObjectsOfTypeAll <NoteCutSoundEffectManager>().LastOrDefault(x => x.isActiveAndEnabled);
            _beatmapObjectManager      = _seManager.GetField <BeatmapObjectManager>("_beatmapObjectManager");
            _cancelSource              = new CancellationTokenSource();
            var level = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.difficultyBeatmap.level;

            if (!(level is CustomPreviewBeatmapLevel))
            {
                yield break;
            }
            _currentLevel = level as CustomPreviewBeatmapLevel;

            //Get DifficultyBeatmap
            BeatmapDifficulty       levelDiff           = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.difficultyBeatmap.difficulty;
            BeatmapCharacteristicSO levelCharacteristic = BS_Utils.Plugin.LevelData.GameplayCoreSceneSetupData.difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic;

            _currentDiffBeatmap = _currentLevel.standardLevelInfoSaveData.difficultyBeatmapSets.First(
                x => x.beatmapCharacteristicName == levelCharacteristic.serializedName).difficultyBeatmaps.First(
                x => x.difficulty == levelDiff.ToString());

            _originalInitData = _timeSync.GetField <AudioTimeSyncController.InitData>("_initData");
            _songStartTime    = _originalInitData.startSongTime;
            //Initialize if everything successfully grabbed
            _init = true;
        }
Exemplo n.º 6
0
        public static void UpdateCoverImage(BeatSaberPlaylist playlist, OpContext context, AssetsFile songsAssetFile)
        {
            CustomLevelLoader loader = new CustomLevelLoader(songsAssetFile, context.Config);

            if (playlist.CoverImageBytes != null && playlist.CoverImageBytes.Length > 0)
            {
                Log.LogMsg($"Loading cover art for playlist ID '{playlist.PlaylistID}'");

                var oldCoverImage = playlist?.LevelPackObject?.CoverImage;
                var oldTex        = playlist?.LevelPackObject?.CoverImage?.Object?.RenderData?.Texture;

                //todo: verify this is a good place to delete stuff
                try
                {
                    playlist.CoverArtSprite             = loader.LoadPackCover(playlist.PlaylistID, playlist.CoverImageBytes);
                    playlist.LevelPackObject.CoverImage = playlist.CoverArtSprite.PtrFrom(playlist.LevelPackObject);
                }
                catch (Exception ex)
                {
                    Log.LogErr("Exception in step 1!", ex);
                    throw;
                }
                try
                {
                    //don't erase base content from the assets, although this definitely leaks textures if you keep switching the stock level pack picture
                    if (!BSConst.KnownLevelPackIDs.Contains(playlist.PlaylistID))
                    {
                        if (oldTex != null)
                        {
                            if (oldTex?.Object != null)
                            {
                                songsAssetFile.DeleteObject(oldTex.Object);
                            }

                            oldTex.Dispose();
                        }
                        if (oldCoverImage != null)
                        {
                            if (oldCoverImage.Object != null)
                            {
                                songsAssetFile.DeleteObject(oldCoverImage.Object);
                            }

                            oldCoverImage.Dispose();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.LogErr("Exception trying to clean up playlist cover art!  This may leak cover images!", ex);
                }
            }
            else
            {
                try
                {
                    if (playlist.LevelPackObject.CoverImage != null)
                    {
                        playlist.CoverArtSprite = playlist.LevelPackObject.CoverImage.Object;
                    }
                    else
                    {
                        playlist.CoverArtSprite = loader.LoadPackCover(playlist.PlaylistID, null);
                    }
                }
                catch (Exception ex)
                {
                    Log.LogErr("Exception in the cover art sprite part!", ex);
                    throw;
                }
                try
                {
                    playlist.LevelPackObject.CoverImage = playlist.CoverArtSprite.PtrFrom(playlist.LevelPackObject);
                }
                catch (Exception ex)
                {
                    Log.LogErr("Exception in the final step!", ex);
                    throw;
                }
            }
            //try queueing a file write op to output the playlist cover image
            try
            {
                var tex = playlist.LevelPackObject?.CoverImage?.Object?.RenderData?.Texture?.Object;
                if (tex == null)
                {
                    throw new Exception("Texture couldn't be loaded from the playlist even though it should have just been set...");
                }

                var qfo = new QueuedFileOp()
                {
                    TargetPath = context.Config.PlaylistsPath.CombineFwdSlash(playlist.PlaylistID + ".png"),
                    Type       = QueuedFileOperationType.WriteFile,
                    SourceData = Utils.ImageUtils.Instance.TextureToPngBytes(tex)
                };
                context.Engine.QueuedFileOperations.Add(qfo);
            }
            catch (Exception ex)
            {
                Log.LogErr($"Exception queueing write op for playlist art on {playlist.PlaylistID}!", ex);
            }
        }
Exemplo n.º 7
0
        private void UpdatePlaylistConfig(AssetsManager manager, BeatSaberPlaylist playlist)
        {
            Log.LogMsg($"Processing playlist ID {playlist.PlaylistID}...");
            var songsAssetFile               = manager.GetAssetsFile(BSConst.KnownFiles.SongsAssetsFilename);
            CustomLevelLoader      loader    = new CustomLevelLoader(songsAssetFile);
            BeatmapLevelPackObject levelPack = songsAssetFile.FindAsset <BeatmapLevelPackObject>(x => x.Object.PackID == playlist.PlaylistID)?.Object;

            //create a new level pack if one waasn't found
            if (levelPack == null)
            {
                Log.LogMsg($"Level pack for playlist '{playlist.PlaylistID}' was not found and will be created");
                levelPack = new BeatmapLevelPackObject(songsAssetFile)
                {
                    Enabled           = 1,
                    GameObject        = null,
                    IsPackAlwaysOwned = true,
                    PackID            = playlist.PlaylistID,
                    Name     = playlist.PlaylistID + BSConst.NameSuffixes.LevelPack,
                    PackName = playlist.PlaylistName
                };
                songsAssetFile.AddObject(levelPack, true);
                var col = new BeatmapLevelCollectionObject(songsAssetFile)
                {
                    Name = playlist.PlaylistID + BSConst.NameSuffixes.LevelCollection
                };
                songsAssetFile.AddObject(col, true);
                levelPack.BeatmapLevelCollection = col.PtrFrom(levelPack);
            }

            playlist.LevelPackObject = levelPack;


            levelPack.PackName = playlist.PlaylistName ?? levelPack.PackName;
            if (playlist.CoverArt != null)
            {
                Log.LogMsg($"Loading cover art for playlist ID '{playlist.PlaylistID}'");

                playlist.CoverArtSprite             = loader.LoadPackCover(playlist.PlaylistID, playlist.CoverArt);
                playlist.LevelPackObject.CoverImage = playlist.CoverArtSprite.PtrFrom(playlist.LevelPackObject);
            }
            else
            {
                if (playlist.LevelPackObject.CoverImage != null)
                {
                    playlist.CoverArtSprite = playlist.LevelPackObject.CoverImage.Object;
                }
                else
                {
                    playlist.CoverArtSprite = loader.LoadPackCover(playlist.PlaylistID, null);
                }
                playlist.LevelPackObject.CoverImage = playlist.CoverArtSprite.PtrFrom(playlist.LevelPackObject);
            }

            //clear out any levels, we'll add them back
            var levelCollection = levelPack.BeatmapLevelCollection.Object;

            levelCollection.BeatmapLevels.ForEach(x => x.Dispose());
            levelCollection.BeatmapLevels.Clear();
            int songCount = 0;

            Log.LogMsg($"Processing songs for playlist ID {playlist.PlaylistID}...");
            var totalSongs = playlist.SongList.Count();
            var songMod    = Math.Ceiling((double)totalSongs / (double)10);

            if (songMod < 1)
            {
                songMod = 1;
            }
            foreach (var song in playlist.SongList.ToList())
            {
                songCount++;
                if (songCount % songMod == 0)
                {
                    Console.WriteLine($"{songCount.ToString().PadLeft(5)} of {totalSongs}...");
                }

                if (UpdateSongConfig(manager, song, loader))
                {
                    if (levelCollection.BeatmapLevels.Any(x => x.Object.LevelID == song.LevelData.LevelID))
                    {
                        Log.LogErr($"Playlist ID '{playlist.PlaylistID}' already contains song ID '{song.SongID}' once, removing the second link");
                    }
                    else
                    {
                        levelCollection.BeatmapLevels.Add(song.LevelData.PtrFrom(levelCollection));
                        continue;
                    }
                }

                playlist.SongList.Remove(song);
            }
            Console.WriteLine($"Proccessed {totalSongs} for playlist ID {playlist.PlaylistID}");
        }
Exemplo n.º 8
0
        private bool UpdateSongConfig(AssetsManager manager, BeatSaberSong song, CustomLevelLoader loader)
        {
            var songsAssetFile           = manager.GetAssetsFile(BSConst.KnownFiles.SongsAssetsFilename);
            BeatmapLevelDataObject level = null;

            if (!string.IsNullOrWhiteSpace(song.SongID))
            {
                var levels = songsAssetFile.FindAssets <BeatmapLevelDataObject>(x => x.Object.LevelID == song.SongID).Select(x => x.Object).ToList();
                if (levels.Count() > 0)
                {
                    if (levels.Count() > 1)
                    {
                        Log.LogErr($"Song ID {song.SongID} already has more than one entry in the assets, this may cause problems!");
                    }
                    else
                    {
                        Log.LogMsg($"Song ID {song.SongID} exists already and won't be loaded");
                    }
                    level          = levels.First();
                    song.LevelData = level;
                    return(true);
                }
                else
                {
                    Log.LogMsg($"Song ID '{song.SongID}' does not exist and will be created");
                }
            }
            if (level != null && !string.IsNullOrWhiteSpace(song.CustomSongFolder))
            {
                Log.LogErr("SongID and CustomSongsFolder are both set and the level already exists.  The existing one will be used and CustomSongsFolder won'tbe imported again.");
                return(false);
            }

            //load new song
            if (!string.IsNullOrWhiteSpace(song.CustomSongFolder))
            {
                try
                {
                    string oggPath;
                    var    deser = loader.DeserializeFromJson(song.CustomSongFolder, song.SongID);
                    var    found = songsAssetFile.FindAssets <BeatmapLevelDataObject>(x => x.Object.LevelID == deser.LevelID).Select(x => x.Object).FirstOrDefault();
                    if (found != null)
                    {
                        Log.LogErr($"No song id was specified, but the level {found.LevelID} is already in the assets, skipping it.");
                        song.LevelData = found;
                        return(true);
                    }
                    level          = loader.LoadSongToAsset(deser, song.CustomSongFolder, out oggPath, true);
                    song.SourceOgg = oggPath;
                }
                catch (Exception ex)
                {
                    Log.LogErr($"Exception loading custom song folder '{song.CustomSongFolder}', skipping it", ex);
                    return(false);
                }

                if (level == null)
                {
                    Log.LogErr($"Song at folder '{song.CustomSongFolder}' failed to load, skipping it");
                    return(false);
                }

                song.LevelData = level;
                return(true);
            }
            //level == null && string.IsNullOrWhiteSpace(song.CustomSongFolder)

            Log.LogErr($"Song ID '{song.SongID}' either was not specified or could not be found and no CustomSongFolder was specified, skipping it.");
            return(false);
        }
Exemplo n.º 9
0
 protected virtual void BackToMenu()
 {
     CustomLevelLoader.LoadLevel("Menu");
 }
Exemplo n.º 10
0
 private void Restart()
 {
     CustomLevelLoader.LoadLevel("Game");
 }
        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);
            }
        }
Exemplo n.º 12
0
 public void PlayGame()
 {
     CustomLevelLoader.LoadLevel("Game");
 }