private void GeneratePlaylistWithMinTime(float minTime, BeatmapDifficulty?difficulty = null, Action <List <IBeatmapLevel> > playlistLoaded = null)
        {
            var totalDuration = 0f;
            var pickFrom      = new List <IPreviewBeatmapLevel>();

            foreach (var pack in beatmapLevelPackCollection.beatmapLevelPacks)
            {
                pickFrom = pickFrom.Union(pack.beatmapLevelCollection.beatmapLevels).ToList();
            }

            var ret = new List <IBeatmapLevel>();

            Action addAnotherSong = null;

            addAnotherSong = async() => {
                var currentIndex = rand.Next(0, pickFrom.Count);
                var currentLevel = pickFrom.ElementAt(currentIndex);
                pickFrom.RemoveAt(currentIndex);

                Action <IBeatmapLevel> SongLoaded = (loadedLevel) =>
                {
                    //If a difficulty was specified, we'll only pick songs that have that difficulty
                    //NOTE: We can't filter out maps during the union because this beatmap data might not
                    //be populated until the level is loaded
                    if (difficulty == null ||
                        loadedLevel.beatmapLevelData.difficultyBeatmapSets.Any(x => x.difficultyBeatmaps.Any(y => y.difficulty == difficulty)))
                    {
                        Logger.Debug($"ADDED: {loadedLevel.songName} ({loadedLevel.songDuration})");
                        totalDuration += loadedLevel.songDuration;
                        ret.Add(loadedLevel);

                        centerViewController.SetProgress(totalDuration / minTime);
                    }

                    if (totalDuration < minTime && pickFrom.Count > 0)
                    {
                        addAnotherSong();
                    }
                    else
                    {
                        playlistLoaded(ret);
                    }
                };

                if (!(currentLevel is IBeatmapLevel))
                {
                    if (await SongHelpers.HasDLCLevel(currentLevel.levelID))
                    {
                        Misc.Logger.Debug("Loading DLC level...");
                        var result = await SongHelpers.GetDLCLevel(currentLevel);

                        if (result != null && !(result?.isError == true))
                        {
                            SongLoaded(result?.beatmapLevel);
                        }
                    }
                    else
                    {
                        Logger.Debug($"Skipping unowned DLC ({currentLevel.songName})");
                        if (pickFrom.Count > 0)
                        {
                            addAnotherSong();
                        }
                        else
                        {
                            playlistLoaded(ret);
                        }
                    }
                }
                else if (currentLevel is CustomLevel)
                {
                    Logger.Debug("Loading custom song data...");
                    SongLoader.Instance.LoadAudioClipForLevel((CustomLevel)currentLevel, SongLoaded);
                }
                else
                {
                    Logger.Debug("Reading OST data without songloader...");
                    SongLoaded(currentLevel as IBeatmapLevel);
                }
            };

            addAnotherSong();
        }
        protected override void DidActivate(bool firstActivation, ActivationType activationType)
        {
            if (activationType == ActivationType.AddedToHierarchy)
            {
                title = Plugin.Name;

                navigationController = BeatSaberUI.CreateViewController <GenericNavigationController>();
                navigationController.didFinishEvent += (_) => mainFlowCoordinator.InvokeMethod("DismissFlowCoordinator", this, null, false);

                if (soloFreePlayFlowCoordinator == null)
                {
                    soloFreePlayFlowCoordinator = Resources.FindObjectsOfTypeAll <SoloFreePlayFlowCoordinator>().First();
                }
                if (_additionalContentModel == null)
                {
                    _additionalContentModel = Resources.FindObjectsOfTypeAll <AdditionalContentModelSO>().First();
                }
                if (_primaryLevelCollection == null)
                {
                    _primaryLevelCollection = _additionalContentModel.alwaysOwnedPacks.First(x => x.packID == "OstVol1").beatmapLevelCollection as BeatmapLevelCollectionSO;
                }
                if (_secondaryLevelCollection == null)
                {
                    _secondaryLevelCollection = _additionalContentModel.alwaysOwnedPacks.First(x => x.packID == "OstVol2").beatmapLevelCollection as BeatmapLevelCollectionSO;
                }
                if (_extrasLevelCollection == null)
                {
                    _extrasLevelCollection = _additionalContentModel.alwaysOwnedPacks.First(x => x.packID == "Extras").beatmapLevelCollection as BeatmapLevelCollectionSO;
                }
                if (beatmapLevelPackCollection == null)
                {
                    beatmapLevelPackCollection = soloFreePlayFlowCoordinator.GetField <IBeatmapLevelPackCollection>("_levelPackCollection");
                }
                if (centerViewController == null)
                {
                    centerViewController = BeatSaberUI.CreateViewController <CenterViewController>();
                    centerViewController.GenerateButtonPressed += () =>
                    {
                        centerViewController.SetUIType(CenterViewController.UIType.ProgressBar);
                        GeneratePlaylistWithMinTime(centerViewController.GetTimeValue(), centerViewController.UseOnlyPreferredDifficulty ? centerViewController.PreferredDifficulty : (BeatmapDifficulty?)null, (playlist) =>
                        {
                            var duration = 0f;
                            foreach (var song in playlist)
                            {
                                duration += song.songDuration;
                                Logger.Debug($"PLAYLIST ITEM: {song.songName} ({song.songDuration})");
                            }
                            Logger.Debug($"TOTAL DURATION: {duration}");

                            centerViewController.SetUIType(CenterViewController.UIType.GenerationButton);

                            //Launch first level
                            Config.Enabled = true;
                            Plugin.instance.loadedLevels = new Queue <IBeatmapLevel>(playlist);
                            var firstMap = SongHelpers.GetClosestDifficultyPreferLower(Plugin.instance.loadedLevels.First(), centerViewController.PreferredDifficulty);

                            SongStitcher.songSwitched -= SongSwitched;
                            SongStitcher.songSwitched += SongSwitched;

                            var playerDataModel = Resources.FindObjectsOfTypeAll <PlayerDataModelSO>().First();
                            MenuTransitionsHelperSO menuTransitionHelper = Resources.FindObjectsOfTypeAll <MenuTransitionsHelperSO>().FirstOrDefault();
                            menuTransitionHelper.StartStandardLevel(firstMap, playerDataModel.currentLocalPlayer.gameplayModifiers, playerDataModel.currentLocalPlayer.playerSpecificSettings, null, "Menu", false, null, SongFinished);
                        });
                    };
                }

                ProvideInitialViewControllers(navigationController);
                SetViewControllersToNavigationConctroller(navigationController, new VRUIViewController[] { centerViewController });
            }
        }
Example #3
0
        public void Update()
        {
            if (gamePauseManager.pause)
            {
                return;                         //Don't do anything if we're paused
            }
            //if (audioTimeSyncController.songTime > 10f && playlist.Count > 0 && !_loadingSong)
            if (audioTimeSyncController.songTime >= audioTimeSyncController.songLength - 0.3f && playlist.Count > 0 && !_loadingSong)
            {
                Logger.Debug("Switching song...");

                audioTimeSyncController.StopSong(); //If we don't, there's a chance the song would progress to `songLength - 0.2f` and the base game would finish the game scene

                Logger.Debug($"Current song: {gameplayCoreSceneSetupData.difficultyBeatmap.level.songName}");

                //Clear out old data from objects that would have ideally been recreated
                ClearOldData();

                //Set up new song
                var   gameplayModifiers      = gameplayCoreSceneSetupData.gameplayModifiers;
                var   playerSpecificSettings = gameplayCoreSceneSetupData.playerSpecificSettings;
                float songSpeedMul           = gameplayModifiers.songSpeedMul;

                var level = playlist.Dequeue();

                //Load song if it's a custom level
                if (level is CustomPreviewBeatmapLevel)
                {
                    var task = Task.Run(async() => await SongHelpers.GetLevelFromPreview(level));
                    task.Wait();

                    var result = task.Result;

                    if (result != null && !(result?.isError == true))
                    {
                        level = result?.beatmapLevel;
                    }
                }

                Logger.Debug($"New song: {level.songName}");

                var oldMap = gameplayCoreSceneSetupData.difficultyBeatmap;

                Logger.Debug($"Getting closest difficulty to {gameplayCoreSceneSetupData.difficultyBeatmap.difficulty} with characteristic {gameplayCoreSceneSetupData.difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic}...");
                IDifficultyBeatmap map = SongHelpers.GetClosestDifficultyPreferLower(level as IBeatmapLevel, (BeatmapDifficulty)preferredDifficulty, gameplayCoreSceneSetupData.difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic);

                Logger.Debug($"Got: {map.difficulty} ({map.parentDifficultyBeatmapSet.beatmapCharacteristic})");

                gameplayCoreSceneSetupData.SetField("_difficultyBeatmap", map);
                BeatmapData beatmapData = BeatDataTransformHelper.CreateTransformedBeatmapData(map.beatmapData, gameplayModifiers, gameplayCoreSceneSetupData.practiceSettings, gameplayCoreSceneSetupData.playerSpecificSettings);
                beatmapDataModel.beatmapData = beatmapData;

                //If this is the last song, set up the viewcontrollers in a way that the proper data is displayed after the song
                var currentPack            = levelDetailViewController.GetField <IBeatmapLevelPack>("_pack");
                var currentPlayer          = levelDetailViewController.GetField <PlayerData>("_playerData");
                var currentShowPlayerStats = levelDetailViewController.GetField <bool>("_showPlayerStats");
                levelDetailViewController.SetData(currentPack, map.level, currentPlayer, currentShowPlayerStats);

                audioTimeSyncController.Init(map.level.beatmapLevelData.audioClip, 0f, map.level.songTimeOffset, songSpeedMul);
                beatmapObjectSpawnController.Init(level.beatsPerMinute, beatmapData.beatmapLinesData.Length, gameplayModifiers.fastNotes ? 20f : (map.noteJumpMovementSpeed == 0 ? map.difficulty.NoteJumpMovementSpeed() : map.noteJumpMovementSpeed), map.noteJumpStartBeatOffset, gameplayModifiers.disappearingArrows, gameplayModifiers.ghostNotes);
                pauseMenuManager.Init(map.level.songName, map.level.songSubName, map.difficulty.Name());

                //Deal with characteristic issues
                Saber.SaberType saberType;
                if (gameplayCoreSceneSetup.UseOneSaberOnly(map.parentDifficultyBeatmapSet.beatmapCharacteristic, playerSpecificSettings, out saberType))
                {
                    gameplayCoreSceneSetup.GetField <PlayerController>("_playerController").AllowOnlyOneSaber(saberType);
                }
                else
                {
                    gameplayCoreSceneSetup
                    .GetField <PlayerController>("_playerController")
                    .GetField <SaberManager>("_saberManager")
                    .SetField("_allowOnlyOneSaber", false);
                }

                Logger.Debug("Starting new song...");
                audioTimeSyncController.StartSong();
                Logger.Debug("Song started!");

                songSwitched?.Invoke(oldMap, map);

                _loadingSong = false;
            }
            //else if (audioTimeSyncController.songTime > 10f && (playlist == null || playlist.Count <= 0) && !_loadingSong)
            else if (audioTimeSyncController.songTime >= audioTimeSyncController.songLength - 0.3f && (playlist == null || playlist.Count <= 0))
            {
                _loadingSong = true; //Only show the following log message once
                Logger.Debug($"Would have switched songs, but playlist was null ({playlist == null}) or empty ({playlist?.Count <= 0})");
            }
        }