public IEnumerator DownloadPlaylistFile(string url, Action <string> playlistDownloaded)
        {
            yield return(null);

            UnityWebRequest www = UnityWebRequest.Get(url);

            www.timeout = 15;
            yield return(www.SendWebRequest());

            if (www.isNetworkError || www.isHttpError)
            {
                Logger.Error($"Unable to connect to BeastSaber playlist API! " + (www.isNetworkError ? $"Network error: {www.error}" : (www.isHttpError ? $"HTTP error: {www.error}" : "Unknown error")));
                playlistDownloaded?.Invoke(null);
            }
            else
            {
                try
                {
                    string docPath = Application.dataPath;
                    docPath = docPath.Substring(0, docPath.Length - 5);
                    docPath = docPath.Substring(0, docPath.LastIndexOf("/"));
                    File.WriteAllText(docPath + "/Playlists/" + Path.GetFileName(www.uri.LocalPath), www.downloadHandler.text);
                    playlistDownloaded?.Invoke(docPath + "/Playlists/" + Path.GetFileName(www.uri.LocalPath));
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to parse response! Exception: " + e);
                    playlistDownloaded?.Invoke(null);
                }
            }
        }
예제 #2
0
        private void SceneManager_activeSceneChanged(Scene from, Scene to)
        {
            Logger.Log($"Active scene changed from \"{from.name}\" to \"{to.name}\"");

            if (from.name == "EmptyTransition" && to.name.Contains("Menu"))
            {
                try
                {
                    PluginUI.Instance.OnLoad();
                    VotingUI.Instance.OnLoad();
                    //TagUI.Instance.OnLoad();
                    if (!PluginConfig.disableSongListTweaks)
                    {
                        SongListTweaks.Instance.OnLoad();
                    }
                }catch (Exception e)
                {
                    Logger.Exception("Exception on scene change: " + e);
                }
            }
            else if (from.name == "GameCore" && to.name.Contains("Menu"))
            {
                TagUI.Instance.OnLoad();
            }
        }
예제 #3
0
        private IEnumerator GetRatingForSong(IBeatmapLevel level)
        {
            UnityWebRequest www = UnityWebRequest.Get($"{PluginConfig.beatsaverURL}/api/songs/search/hash/{level.levelID.Substring(0, 32)}");

            yield return(www.SendWebRequest());

            if (www.isNetworkError || www.isHttpError)
            {
                Logger.Error($"Unable to connect to {PluginConfig.beatsaverURL}! " + (www.isNetworkError ? $"Network error: {www.error}" : (www.isHttpError ? $"HTTP error: {www.error}" : "Unknown error")));
            }
            else
            {
                try
                {
                    _firstVote = true;

                    JSONNode node = JSON.Parse(www.downloadHandler.text);

                    _lastBeatSaverSong = Song.FromSearchNode(node["songs"][0]);

                    _ratingText.text = (int.Parse(_lastBeatSaverSong.upvotes) - int.Parse(_lastBeatSaverSong.downvotes)).ToString();

                    _upvoteButton.interactable   = (PluginConfig.apiAccessToken != PluginConfig.apiTokenPlaceholder);
                    _downvoteButton.interactable = (PluginConfig.apiAccessToken != PluginConfig.apiTokenPlaceholder);
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to get song rating! Excpetion: " + e);
                }
            }
        }
        public IEnumerator GetInfoForSong(Playlist playlist, PlaylistSong song, Action <Song> songCallback)
        {
            string url = $"{PluginConfig.beatsaverURL}/api/songs/detail/{song.key}";

            if (!string.IsNullOrEmpty(playlist.customDetailUrl))
            {
                url = playlist.customDetailUrl + song.key;
            }

            UnityWebRequest www = UnityWebRequest.Get(url);

            www.timeout = 15;
            yield return(www.SendWebRequest());

            if (www.isNetworkError || www.isHttpError)
            {
                Logger.Error($"Unable to connect to {PluginConfig.beatsaverURL}! " + (www.isNetworkError ? $"Network error: {www.error}" : (www.isHttpError ? $"HTTP error: {www.error}" : "Unknown error")));
            }
            else
            {
                try
                {
                    JSONNode node = JSON.Parse(www.downloadHandler.text);
                    songCallback?.Invoke(new Song(node["song"]));
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to parse response! Exception: " + e);
                }
            }
        }
        protected override void DidActivate(bool firstActivation, ActivationType type)
        {
            if (firstActivation && type == ActivationType.AddedToHierarchy)
            {
                RemoveCustomUIElements(rectTransform);

                Destroy(GetComponentsInChildren <LevelParamsPanel>().First(x => x.name == "LevelParamsPanel").gameObject);

                RectTransform yourStats = GetComponentsInChildren <RectTransform>(true).First(x => x.name == "YourStats");
                yourStats.gameObject.SetActive(true);

                RectTransform buttonsRect = GetComponentsInChildren <RectTransform>().First(x => x.name == "Buttons");
                buttonsRect.anchoredPosition = new Vector2(0f, 6f);

                TextMeshProUGUI[] _textComponents = GetComponentsInChildren <TextMeshProUGUI>();

                try
                {
                    songNameText = _textComponents.First(x => x.name == "SongNameText");
                    _textComponents.First(x => x.name == "Title").text = "Playlist";

                    _textComponents.First(x => x.name == "YourStatsTitle").text = "Playlist Info";

                    _textComponents.First(x => x.name == "HighScoreText").text = "Author";
                    authorText = _textComponents.First(x => x.name == "HighScoreValueText");
                    authorText.rectTransform.sizeDelta = new Vector2(24f, 0f);

                    _textComponents.First(x => x.name == "MaxComboText").text = "Total songs";
                    totalSongsText = _textComponents.First(x => x.name == "MaxComboValueText");

                    _textComponents.First(x => x.name == "MaxRankText").text = "Downloaded";
                    _textComponents.First(x => x.name == "MaxRankText").rectTransform.sizeDelta = new Vector2(18f, 3f);
                    downloadedSongsText = _textComponents.First(x => x.name == "MaxRankValueText");
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to convert detail view controller! Exception:  " + e);
                }

                _selectButton = GetComponentsInChildren <Button>().First(x => x.name == "PlayButton");
                _selectButton.SetButtonText(_selectButtonText);
                _selectButton.onClick.RemoveAllListeners();
                _selectButton.onClick.AddListener(() => { selectButtonPressed?.Invoke(_currentPlaylist); });

                if (addDownloadButton)
                {
                    _downloadButton = GetComponentsInChildren <Button>().First(x => x.name == "PracticeButton");
                    _downloadButton.GetComponentsInChildren <Image>().First(x => x.name == "Icon").sprite = Base64Sprites.DownloadIcon;
                    _downloadButton.onClick.RemoveAllListeners();
                    _downloadButton.onClick.AddListener(() => { downloadButtonPressed?.Invoke(_currentPlaylist); });
                }
                else
                {
                    Destroy(GetComponentsInChildren <Button>().First(x => x.name == "PracticeButton").gameObject);
                }
            }
        }
예제 #6
0
        private IEnumerator GetRatingForSong(IBeatmapLevel level)
        {
            UnityWebRequest www = UnityWebRequest.Get($"{PluginConfig.beatsaverURL}/api/songs/search/hash/{level.levelID.Substring(0, 32)}");

            yield return(www.SendWebRequest());

            if (www.isNetworkError || www.isHttpError)
            {
                Logger.Error($"Unable to connect to {PluginConfig.beatsaverURL}! " + (www.isNetworkError ? $"Network error: {www.error}" : (www.isHttpError ? $"HTTP error: {www.error}" : "Unknown error")));
            }
            else
            {
                try
                {
                    _firstVote = true;

                    JSONNode node = JSON.Parse(www.downloadHandler.text);

                    if (node["songs"].Count > 0)
                    {
                        _lastBeatSaverSong = Song.FromSearchNode(node["songs"][0]);

                        _ratingText.text = (int.Parse(_lastBeatSaverSong.upvotes) - int.Parse(_lastBeatSaverSong.downvotes)).ToString();

                        bool canVote = (PluginConfig.apiAccessToken != PluginConfig.apiTokenPlaceholder || (VRPlatformHelper.instance.vrPlatformSDK == VRPlatformHelper.VRPlatformSDK.OpenVR || Environment.CommandLine.ToLower().Contains("-vrmode oculus") || Environment.CommandLine.ToLower().Contains("fpfc")));

                        _upvoteButton.interactable   = canVote;
                        _downvoteButton.interactable = canVote;

                        _reviewButton.interactable = true;

                        if (PluginConfig.votedSongs.ContainsKey(_lastLevel.levelID.Substring(0, 32)))
                        {
                            switch (PluginConfig.votedSongs[_lastLevel.levelID.Substring(0, 32)].voteType)
                            {
                            case VoteType.Upvote: { _upvoteButton.interactable = false; } break;

                            case VoteType.Downvote: { _downvoteButton.interactable = false; } break;
                            }
                        }
                    }
                    else
                    {
                        Logger.Error("Song doesn't exist on BeatSaver!");
                    }
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to get song rating! Excpetion: " + e);
                }
            }
        }
예제 #7
0
        private void OnMenuSceneLoadedFresh()
        {
            try
            {
                PluginUI.Instance.OnLoad();
                VotingUI.Instance.OnLoad();
                SongListTweaks.Instance.OnLoad();

                GetUserInfo.GetUserName();
            }
            catch (Exception e)
            {
                Logger.Exception("Exception on fresh menu scene change: " + e);
            }
        }
        public IEnumerator GetPlaylists()
        {
            yield return(null);

            _loadingIndicator.SetActive(true);
            _playlistsListViewController.SetContent(null);

            UnityWebRequest www = UnityWebRequest.Get(playlistAPI_URL);

            www.timeout = 15;
            yield return(www.SendWebRequest());

            if (www.isNetworkError || www.isHttpError)
            {
                Logger.Error($"Unable to connect to BeastSaber playlist API! " + (www.isNetworkError ? $"Network error: {www.error}" : (www.isHttpError ? $"HTTP error: {www.error}" : "Unknown error")));
                _loadingIndicator.SetActive(false);
            }
            else
            {
                try
                {
                    JSONNode node = JSON.Parse(www.downloadHandler.text);

                    playlists.Clear();

                    for (int i = 0; i < node.Count; i++)
                    {
                        playlists.Add(new Playlist(node[i]));
                    }


                    _loadingIndicator.SetActive(false);
                    _playlistsListViewController.SetContent(playlists);
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to parse response! Exception: " + e);
                    _loadingIndicator.SetActive(false);
                }
            }
        }
        public IEnumerator GetSearchResults(int page, string search)
        {
            yield return(null);

            _moreSongsListViewController.SetLoadingState(true);
            _moreSongsListViewController.TogglePageUpDownButtons((page > 0), true);
            _moreSongsListViewController.SetContent(null);

            UnityWebRequest www = UnityWebRequest.Get($"{PluginConfig.beatsaverURL}/api/songs/search/all/{search}");

            www.timeout = 30;
            yield return(www.SendWebRequest());

            if (www.isNetworkError || www.isHttpError)
            {
                Logger.Error($"Unable to connect to {PluginConfig.beatsaverURL}! " + (www.isNetworkError ? $"Network error: {www.error}" : (www.isHttpError ? $"HTTP error: {www.error}" : "Unknown error")));
            }
            else
            {
                try
                {
                    JSONNode node = JSON.Parse(www.downloadHandler.text);

                    currentPageSongs.Clear();

                    for (int i = (page * songsPerPage); i < Math.Min(node["songs"].Count, ((page + 1) * songsPerPage)); i++)
                    {
                        currentPageSongs.Add(Song.FromSearchNode(node["songs"][i]));
                    }

                    _moreSongsListViewController.SetContent(currentPageSongs);
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to parse response! Exception: " + e);
                }
            }
            _moreSongsListViewController.SetLoadingState(false);
        }
예제 #10
0
        //Time      - Downloads
        //BPM       - Plays
        //Notes     - BPM
        //Obstacles - Upvotes
        //Bombs     - Downvotes

        protected override void DidActivate(bool firstActivation, ActivationType type)
        {
            if (firstActivation)
            {
                gameObject.SetActive(true);
                _levelDetails = GetComponentsInChildren <StandardLevelDetailView>(true).First(x => x.name == "LevelDetail");
                _levelDetails.gameObject.SetActive(true);

                RemoveCustomUIElements(rectTransform);

                _levelParams = GetComponentsInChildren <LevelParamsPanel>().First(x => x.name == "LevelParamsPanel");

                foreach (HoverHint hint in _levelParams.transform.GetComponentsInChildren <HoverHint>())
                {
                    switch (hint.name)
                    {
                    case "Time":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Sprites.DownloadIcon;
                    }; break;

                    case "BPM":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Sprites.PlayIcon;
                    }; break;

                    case "NotesCount":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Resources.FindObjectsOfTypeAll <Sprite>().First(x => x.name == "MetronomeIcon");
                    }; break;

                    case "ObstaclesCount":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Sprites.ThumbUp;
                    }; break;

                    case "BombsCount":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Sprites.ThumbDown;
                    }; break;
                    }

                    Destroy(hint);
                }

                RectTransform yourStats = GetComponentsInChildren <RectTransform>().First(x => x.name == "Stats");
                yourStats.gameObject.SetActive(true);

                TextMeshProUGUI[] _textComponents = GetComponentsInChildren <TextMeshProUGUI>();

                try
                {
                    songNameText = _textComponents.First(x => x.name == "SongNameText");

                    downloadsText          = _textComponents.First(x => x.name == "ValueText" && x.transform.parent.name == "Time");
                    downloadsText.fontSize = 3f;

                    playsText          = _textComponents.First(x => x.name == "ValueText" && x.transform.parent.name == "BPM");
                    playsText.fontSize = 3f;

                    _textComponents.First(x => x.name == "Title" && x.transform.parent.name == "MaxRank").text = "Expert/+";
                    difficulty1Text = _textComponents.First(x => x.name == "Value" && x.transform.parent.name == "MaxRank");

                    _textComponents.First(x => x.name == "Title" && x.transform.parent.name == "Highscore").text = "Hard";
                    difficulty2Text = _textComponents.First(x => x.name == "Value" && x.transform.parent.name == "Highscore");

                    _textComponents.First(x => x.name == "Title" && x.transform.parent.name == "MaxCombo").text = "Easy/Normal";
                    difficulty3Text = _textComponents.First(x => x.name == "Value" && x.transform.parent.name == "MaxCombo");
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to convert detail view controller! Exception:  " + e);
                }

                _downloadButton = _levelDetails.playButton;
                _downloadButton.SetButtonText("DOWNLOAD");
                _downloadButton.ToggleWordWrapping(false);
                _downloadButton.onClick.RemoveAllListeners();
                _downloadButton.onClick.AddListener(() => { downloadButtonPressed?.Invoke(_currentSong); });
                (_downloadButton.transform as RectTransform).sizeDelta = new Vector2(26f, 8.8f);

                _favoriteButton = _levelDetails.practiceButton;
                _favoriteButton.SetButtonIcon(Sprites.AddToFavorites);
                _favoriteButton.onClick.RemoveAllListeners();
                _favoriteButton.onClick.AddListener(() => { favoriteButtonPressed?.Invoke(_currentSong); });

                coverImage = _levelDetails.GetPrivateField <Image>("_coverImage");
            }
        }
예제 #11
0
        protected override void DidActivate(bool firstActivation, ActivationType type)
        {
            if (firstActivation && type == ActivationType.AddedToHierarchy)
            {
                gameObject.SetActive(true);
                _levelDetails = GetComponentsInChildren <StandardLevelDetailView>(true).First(x => x.name == "LevelDetail");
                _levelDetails.gameObject.SetActive(true);

                RemoveCustomUIElements(rectTransform);

                Destroy(GetComponentsInChildren <LevelParamsPanel>().First(x => x.name == "LevelParamsPanel").gameObject);

                RectTransform yourStats = GetComponentsInChildren <RectTransform>(true).First(x => x.name == "Stats");
                yourStats.gameObject.SetActive(true);

                //RectTransform buttonsRect = GetComponentsInChildren<RectTransform>().First(x => x.name == "PlayButtons");
                //buttonsRect.anchoredPosition = new Vector2(0f, 6f);

                TextMeshProUGUI[] _textComponents = GetComponentsInChildren <TextMeshProUGUI>();

                try
                {
                    songNameText = _textComponents.First(x => x.name == "SongNameText");
                    _textComponents.First(x => x.name == "Title").text = "Playlist";

                    _textComponents.First(x => x.name == "Title" && x.transform.parent.name == "MaxCombo").text = "Author";
                    authorText = _textComponents.First(x => x.name == "Value" && x.transform.parent.name == "MaxCombo");
                    authorText.rectTransform.sizeDelta = new Vector2(24f, 0f);

                    _textComponents.First(x => x.name == "Title" && x.transform.parent.name == "Highscore").text = "Total songs";
                    totalSongsText = _textComponents.First(x => x.name == "Value" && x.transform.parent.name == "Highscore");

                    _textComponents.First(x => x.name == "Title" && x.transform.parent.name == "MaxRank").text = "Downloaded";
                    downloadedSongsText = _textComponents.First(x => x.name == "Value" && x.transform.parent.name == "MaxRank");
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to convert detail view controller! Exception:  " + e);
                }

                _selectButton = _levelDetails.playButton;
                _selectButton.SetButtonText(_selectButtonText);
                _selectButton.ToggleWordWrapping(false);
                _selectButton.onClick.RemoveAllListeners();
                _selectButton.onClick.AddListener(() => { selectButtonPressed?.Invoke(_currentPlaylist); });

                if (addDownloadButton)
                {
                    _downloadButton = _levelDetails.practiceButton;
                    _downloadButton.SetButtonIcon(Sprites.DownloadIcon);
                    _downloadButton.onClick.RemoveAllListeners();
                    _downloadButton.onClick.AddListener(() => { downloadButtonPressed?.Invoke(_currentPlaylist); });
                }
                else
                {
                    Destroy(_levelDetails.practiceButton.gameObject);
                }

                coverImage = _levelDetails.GetPrivateField <Image>("_coverImage");
            }
        }
예제 #12
0
        public Playlist(JSONNode playlistNode)
        {
            string image = playlistNode["image"].Value;

            if (!string.IsNullOrEmpty(image))
            {
                try
                {
                    icon = Base64Sprites.Base64ToSprite(image.Substring(image.IndexOf(",") + 1));
                }
                catch
                {
                    Logger.Exception("Unable to convert playlist image to sprite!");
                    icon = Base64Sprites.BeastSaberLogo;
                }
            }
            else
            {
                icon = Base64Sprites.BeastSaberLogo;
            }
            playlistTitle    = playlistNode["playlistTitle"];
            playlistAuthor   = playlistNode["playlistAuthor"];
            customDetailUrl  = playlistNode["customDetailUrl"];
            customArchiveUrl = playlistNode["customArchiveUrl"];
            if (!string.IsNullOrEmpty(customDetailUrl))
            {
                if (!customDetailUrl.EndsWith("/"))
                {
                    customDetailUrl += "/";
                }
                Logger.Log("Found playlist with customDetailUrl! Name: " + playlistTitle + ", CustomDetailUrl: " + customDetailUrl);
            }
            if (!string.IsNullOrEmpty(customArchiveUrl) && customArchiveUrl.Contains("[KEY]"))
            {
                Logger.Log("Found playlist with customArchiveUrl! Name: " + playlistTitle + ", CustomArchiveUrl: " + customArchiveUrl);
            }

            songs = new List <PlaylistSong>();

            foreach (JSONNode node in playlistNode["songs"].AsArray)
            {
                PlaylistSong song = new PlaylistSong();
                song.key      = node["key"];
                song.songName = node["songName"];
                song.levelId  = node["levelId"];

                songs.Add(song);
            }

            if (playlistNode["playlistSongCount"] != null)
            {
                songCount = playlistNode["playlistSongCount"].AsInt;
            }
            if (playlistNode["fileLoc"] != null)
            {
                fileLoc = playlistNode["fileLoc"];
            }

            if (playlistNode["playlistURL"] != null)
            {
                fileLoc = playlistNode["playlistURL"];
            }
        }
예제 #13
0
        public IEnumerator DownloadSongCoroutine(Song songInfo)
        {
            songInfo.songQueueState = SongQueueState.Downloading;

            UnityWebRequest www;
            bool            timeout = false;
            float           time    = 0f;
            UnityWebRequestAsyncOperation asyncRequest;

            try
            {
                www = UnityWebRequest.Get(songInfo.downloadUrl);

                asyncRequest = www.SendWebRequest();
            }
            catch (Exception e)
            {
                Logger.Error(e);
                songInfo.songQueueState      = SongQueueState.Error;
                songInfo.downloadingProgress = 1f;

                yield break;
            }

            while ((!asyncRequest.isDone || songInfo.downloadingProgress != 1f) && songInfo.songQueueState != SongQueueState.Error)
            {
                yield return(null);

                time += Time.deltaTime;

                if ((time >= 5f && asyncRequest.progress == 0f) || songInfo.songQueueState == SongQueueState.Error)
                {
                    www.Abort();
                    timeout = true;
                    Logger.Error("Connection timed out!");
                }

                songInfo.downloadingProgress = asyncRequest.progress;
            }


            if (www.isNetworkError || www.isHttpError || timeout || songInfo.songQueueState == SongQueueState.Error)
            {
                songInfo.songQueueState = SongQueueState.Error;
                Logger.Error("Unable to download song! " + (www.isNetworkError ? $"Network error: {www.error}" : (www.isHttpError ? $"HTTP error: {www.error}" : "Unknown error")));
            }
            else
            {
                Logger.Log("Received response from BeatSaver.com...");

                string docPath         = "";
                string customSongsPath = "";

                byte[] data = www.downloadHandler.data;

                Stream zipStream = null;

                try
                {
                    docPath         = Application.dataPath;
                    docPath         = docPath.Substring(0, docPath.Length - 5);
                    docPath         = docPath.Substring(0, docPath.LastIndexOf("/"));
                    customSongsPath = docPath + "/CustomSongs/" + songInfo.id + "/";
                    if (!Directory.Exists(customSongsPath))
                    {
                        Directory.CreateDirectory(customSongsPath);
                    }
                    zipStream = new MemoryStream(data);
                    Logger.Log("Downloaded zip!");
                }
                catch (Exception e)
                {
                    Logger.Exception(e);
                    songInfo.songQueueState = SongQueueState.Error;
                    yield break;
                }

                yield return(new WaitWhile(() => _extractingZip)); //because extracting several songs at once sometimes hangs the game

                Task extract = ExtractZipAsync(songInfo, zipStream, customSongsPath);
                yield return(new WaitWhile(() => !extract.IsCompleted));

                songDownloaded?.Invoke(songInfo);
            }
        }
예제 #14
0
        public static void ReloadPlaylists(bool fullRefresh = true)
        {
            try
            {
                List <string> playlistFiles = new List <string>();

                if (PluginConfig.beatDropInstalled)
                {
                    string[] beatDropJSONPlaylists   = Directory.GetFiles(Path.Combine(PluginConfig.beatDropPlaylistsLocation, "playlists"), "*.json");
                    string[] beatDropBPLISTPlaylists = Directory.GetFiles(Path.Combine(PluginConfig.beatDropPlaylistsLocation, "playlists"), "*.bplist");
                    playlistFiles.AddRange(beatDropJSONPlaylists);
                    playlistFiles.AddRange(beatDropBPLISTPlaylists);
                    Logger.Log($"Found {beatDropJSONPlaylists.Length + beatDropBPLISTPlaylists.Length} playlists in BeatDrop folder");
                }

                string[] localJSONPlaylists   = Directory.GetFiles(Path.Combine(Environment.CurrentDirectory, "Playlists"), "*.json");
                string[] localBPLISTPlaylists = Directory.GetFiles(Path.Combine(Environment.CurrentDirectory, "Playlists"), "*.bplist");
                playlistFiles.AddRange(localJSONPlaylists);
                playlistFiles.AddRange(localBPLISTPlaylists);

                Logger.Log($"Found {localJSONPlaylists.Length + localBPLISTPlaylists.Length} playlists in Playlists folder");

                if (fullRefresh)
                {
                    loadedPlaylists.Clear();

                    foreach (string path in playlistFiles)
                    {
                        try
                        {
                            Playlist playlist = Playlist.LoadPlaylist(path);
                            if (Path.GetFileName(path) == "favorites.json" && playlist.playlistTitle == "Your favorite songs")
                            {
                                continue;
                            }
                            loadedPlaylists.Add(playlist);
                            Logger.Log($"Found \"{playlist.playlistTitle}\" by {playlist.playlistAuthor}");
                        }
                        catch (Exception e)
                        {
                            Logger.Log($"Unable to parse playlist @ {path}! Exception: {e}");
                        }
                    }
                }
                else
                {
                    foreach (string path in playlistFiles)
                    {
                        if (!loadedPlaylists.Any(x => x.fileLoc == path))
                        {
                            Logger.Log("Found new playlist! Path: " + path);
                            try
                            {
                                Playlist playlist = Playlist.LoadPlaylist(path);
                                if (Path.GetFileName(path) == "favorites.json" && playlist.playlistTitle == "Your favorite songs")
                                {
                                    continue;
                                }
                                loadedPlaylists.Add(playlist);
                                Logger.Log($"Found \"{playlist.playlistTitle}\" by {playlist.playlistAuthor}");

                                if (SongLoader.AreSongsLoaded)
                                {
                                    MatchSongsForPlaylist(playlist);
                                }
                            }
                            catch (Exception e)
                            {
                                Logger.Log($"Unable to parse playlist @ {path}! Exception: {e}");
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Logger.Exception("Unable to load playlists! Exception: " + e);
            }
        }
        //Time      - Downloads
        //BPM       - Plays
        //Notes     - BPM
        //Obstacles - Upvotes
        //Bombs     - Downvotes

        protected override void DidActivate(bool firstActivation, ActivationType type)
        {
            if (firstActivation && type == ActivationType.AddedToHierarchy)
            {
                RemoveCustomUIElements(rectTransform);

                _levelDetails = GetComponentsInChildren <LevelParamsPanel>().First(x => x.name == "LevelParamsPanel");
                foreach (HoverHint hint in _levelDetails.transform.GetComponentsInChildren <HoverHint>())
                {
                    switch (hint.name)
                    {
                    case "Time":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Base64Sprites.DownloadIcon;
                    }; break;

                    case "BPM":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Base64Sprites.PlayIcon;
                    }; break;

                    case "NotesCount":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Resources.FindObjectsOfTypeAll <Sprite>().First(x => x.name == "MetronomeIcon");
                    }; break;

                    case "ObstaclesCount":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Base64Sprites.ThumbUp;
                    }; break;

                    case "BombsCount":
                    {
                        hint.GetComponentInChildren <Image>().sprite = Base64Sprites.ThumbDown;
                    }; break;
                    }

                    Destroy(hint);
                }

                RectTransform yourStats = GetComponentsInChildren <RectTransform>(true).First(x => x.name == "YourStats");
                yourStats.gameObject.SetActive(true);

                RectTransform buttonsRect = GetComponentsInChildren <RectTransform>().First(x => x.name == "Buttons");
                buttonsRect.anchoredPosition = new Vector2(0f, 6f);

                TextMeshProUGUI[] _textComponents = GetComponentsInChildren <TextMeshProUGUI>();

                try
                {
                    songNameText = _textComponents.First(x => x.name == "SongNameText");

                    downloadsText          = _textComponents.First(x => x.name == "ValueText" && x.transform.parent.name == "Time");
                    downloadsText.fontSize = 3f;

                    playsText          = _textComponents.First(x => x.name == "ValueText" && x.transform.parent.name == "BPM");
                    playsText.fontSize = 3f;

                    _textComponents.First(x => x.name == "YourStatsTitle").text = "Difficulties";

                    _textComponents.First(x => x.name == "HighScoreText").text = "Expert/+";
                    difficulty1Text = _textComponents.First(x => x.name == "HighScoreValueText");

                    _textComponents.First(x => x.name == "MaxComboText").text = "Hard";
                    difficulty2Text = _textComponents.First(x => x.name == "MaxComboValueText");

                    _textComponents.First(x => x.name == "MaxRankText").text = "Easy/Normal";
                    _textComponents.First(x => x.name == "MaxRankText").rectTransform.sizeDelta = new Vector2(18f, 3f);
                    difficulty3Text = _textComponents.First(x => x.name == "MaxRankValueText");
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to convert detail view controller! Exception:  " + e);
                }

                _downloadButton = GetComponentsInChildren <Button>().First(x => x.name == "PlayButton");
                _downloadButton.GetComponentsInChildren <TextMeshProUGUI>().First().text = "DOWNLOAD";
                _downloadButton.onClick.RemoveAllListeners();
                _downloadButton.onClick.AddListener(() => { downloadButtonPressed?.Invoke(_currentSong); });

                _favoriteButton = GetComponentsInChildren <Button>().First(x => x.name == "PracticeButton");
                _favoriteButton.GetComponentsInChildren <Image>().First(x => x.name == "Icon").sprite = Base64Sprites.AddToFavorites;
                _favoriteButton.onClick.RemoveAllListeners();
                _favoriteButton.onClick.AddListener(() => { favoriteButtonPressed?.Invoke(_currentSong); });
            }
        }
        public IEnumerator GetInfoForSong(Playlist playlist, PlaylistSong song, Action <Song> songCallback)
        {
            string url        = "";
            bool   _usingHash = false;

            if (!string.IsNullOrEmpty(song.key))
            {
                url = $"{PluginConfig.beatsaverURL}/api/songs/detail/{song.key}";
                if (!string.IsNullOrEmpty(playlist.customDetailUrl))
                {
                    url = playlist.customDetailUrl + song.key;
                }
            }
            else if (!string.IsNullOrEmpty(song.hash))
            {
                url        = $"{PluginConfig.beatsaverURL}/api/songs/search/hash/{song.hash}";
                _usingHash = true;
            }
            else if (!string.IsNullOrEmpty(song.levelId))
            {
                string hash = CustomHelpers.CheckHex(song.levelId.Substring(0, Math.Min(32, song.levelId.Length)));
                url        = $"{PluginConfig.beatsaverURL}/api/songs/search/hash/{hash}";
                _usingHash = true;
            }
            else
            {
                yield break;
            }

            UnityWebRequest www = UnityWebRequest.Get(url);

            www.timeout = 15;
            yield return(www.SendWebRequest());

            if (www.isNetworkError || www.isHttpError)
            {
                Logger.Error($"Unable to connect to {PluginConfig.beatsaverURL}! " + (www.isNetworkError ? $"Network error: {www.error}" : (www.isHttpError ? $"HTTP error: {www.error}" : "Unknown error")));
            }
            else
            {
                try
                {
                    JSONNode node = JSON.Parse(www.downloadHandler.text);

                    if (_usingHash)
                    {
                        if (node["songs"].Count == 0)
                        {
                            Logger.Error($"Song {song.songName} doesn't exist on BeatSaver!");
                            songCallback?.Invoke(null);
                            yield break;
                        }
                        songCallback?.Invoke(Song.FromSearchNode(node["songs"][0]));
                    }
                    else
                    {
                        songCallback?.Invoke(new Song(node["song"]));
                    }
                }
                catch (Exception e)
                {
                    Logger.Exception("Unable to parse response! Exception: " + e);
                }
            }
        }
예제 #17
0
        static TableCell Postfix(TableCell __result, LevelPackLevelsTableView __instance, int row)
        {
            try
            {
                if (!PluginConfig.enableSongIcons)
                {
                    return(__result);
                }

                bool showHeader = __instance.GetPrivateField <bool>("_showLevelPackHeader");

                if (row == 0 && showHeader)
                {
                    return(__result);
                }

                string levelId = __instance.GetPrivateField <IBeatmapLevelPack>("_pack").beatmapLevelCollection.beatmapLevels[(showHeader ? (row - 1) : row)].levelID;
                levelId = levelId.Substring(0, Math.Min(32, levelId.Length));

                UnityEngine.UI.Image icon = null;

                UnityEngine.UI.Image[] levelIcons = __result.GetPrivateField <UnityEngine.UI.Image[]>("_beatmapCharacteristicImages");
                float[] levelIconAlphas           = __result.GetPrivateField <float[]>("_beatmapCharacteristicAlphas");

                if (levelIcons.Any(x => x.name == "LevelTypeIconExtra"))
                {
                    icon = levelIcons.First(x => x.name == "LevelTypeIconExtra");
                }
                else
                {
                    icon = GameObject.Instantiate(__result.GetComponentsInChildren <UnityEngine.UI.Image>().First(x => x.name == "LevelTypeIcon0"), __result.transform, true);

                    (icon.transform as RectTransform).anchoredPosition = new Vector2(-14.5f, 0f);
                    icon.transform.name = "LevelTypeIconExtra";

                    levelIcons = levelIcons.AddToArray(icon);
                    __result.SetPrivateField("_beatmapCharacteristicImages", levelIcons);

                    levelIconAlphas = levelIconAlphas.AddToArray(0.1f);
                    __result.SetPrivateField("_beatmapCharacteristicAlphas", levelIconAlphas);

                    foreach (var levelIcon in levelIcons)
                    {
                        levelIcon.rectTransform.anchoredPosition = new Vector2(levelIcon.rectTransform.anchoredPosition.x, -2f);
                    }
                }

                if (PluginConfig.favoriteSongs.Any(x => x.StartsWith(levelId)))
                {
                    levelIconAlphas[3] = 1f;
                    icon.sprite        = Sprites.StarFull;
                }
                else if (PluginConfig.votedSongs.ContainsKey(levelId))
                {
                    switch (PluginConfig.votedSongs[levelId].voteType)
                    {
                    case VoteType.Upvote:
                    {
                        levelIconAlphas[3] = 1f;
                        icon.sprite        = Sprites.ThumbUp;
                    }
                    break;

                    case VoteType.Downvote:
                    {
                        levelIconAlphas[3] = 1f;
                        icon.sprite        = Sprites.ThumbDown;
                    }
                    break;
                    }
                }
                else
                {
                    levelIconAlphas[3] = 0.1f;
                    icon.sprite        = Sprites.StarFull;
                }
            }
            catch (Exception e)
            {
                Logger.Exception("Unable to create extra icon! Exception: " + e);
            }
            return(__result);
        }