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); } } }
private void _simpleDialog_didFinishEvent(SimpleDialogPromptViewController sender, bool delete) { _freePlayFlowCoordinator.InvokePrivateMethod("DismissViewController", new object[] { _simpleDialog, null, false }); if (delete) { try { SongDownloader.Instance.DeleteSong(new Song(SongLoader.CustomLevels.First(x => x.levelID == _detailViewController.difficultyBeatmap.level.levelID))); List <IBeatmapLevel> levels = _levelListViewController.GetPrivateField <IBeatmapLevel[]>("_levels").ToList(); int selectedIndex = levels.IndexOf(_detailViewController.difficultyBeatmap.level); if (selectedIndex > -1) { int removedLevels = levels.RemoveAll(x => x == _detailViewController.difficultyBeatmap.level); Logger.Log("Removed " + removedLevels + " level(s) from song list!"); if (selectedIndex > 0) { selectedIndex--; } _levelListViewController.SetLevels(levels.ToArray()); TableView listTableView = _levelListViewController.GetPrivateField <LevelListTableView>("_levelListTableView").GetPrivateField <TableView>("_tableView"); listTableView.ScrollToRow(selectedIndex, false); listTableView.SelectRow(selectedIndex, true); } }catch (Exception e) { Logger.Error("Unable to delete song! Exception: " + e); } } }
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(); } }
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 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); } } }
private IEnumerator VoteForSong(bool upvote) { Logger.Log($"Voting..."); _upvoteButton.interactable = false; _downvoteButton.interactable = false; UnityWebRequest voteWWW = UnityWebRequest.Get($"{PluginConfig.beatsaverURL}/api/songs/vote/{_lastBeatSaverSong.id}/{(upvote ? 1 : 0)}/{PluginConfig.apiAccessToken}"); voteWWW.timeout = 30; yield return(voteWWW.SendWebRequest()); if (voteWWW.isNetworkError || voteWWW.isHttpError) { Logger.Error(voteWWW.error); _ratingText.text = voteWWW.error; } else { if (!_firstVote) { yield return(new WaitForSecondsRealtime(3f)); } _firstVote = false; _upvoteButton.interactable = true; _downvoteButton.interactable = true; switch (voteWWW.responseCode) { case 200: { JSONNode node = JSON.Parse(voteWWW.downloadHandler.text); _ratingText.text = (int.Parse(node["upVotes"]) - int.Parse(node["downVotes"])).ToString(); }; break; case 403: { _ratingText.text = "Read-only token"; }; break; case 401: { _ratingText.text = "Token not found"; }; break; case 400: { _ratingText.text = "Bad token"; }; break; default: { _ratingText.text = "Error " + voteWWW.responseCode; }; break; } } }
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); } } }
public void DownloadAllSongsFromQueue() { Logger.Log("Downloading all songs from queue..."); for (int i = 0; i < Math.Min(PluginConfig.maxSimultaneousDownloads, queuedSongs.Count); i++) { StartCoroutine(DownloadSong(queuedSongs[i])); } }
public void AbortDownloads() { Logger.Log("Cancelling downloads..."); foreach (Song song in queuedSongs.Where(x => x.songQueueState == SongQueueState.Downloading || x.songQueueState == SongQueueState.Queued)) { song.songQueueState = SongQueueState.Error; } Refresh(); allSongsDownloaded?.Invoke(); }
private void _standardLevelResultsViewController_continueButtonPressedEvent(ResultsViewController sender) { try { TableView _levelListTableView = _levelListViewController.GetComponentInChildren <TableView>(); _levelListTableView.RefreshTable(); }catch (Exception e) { Logger.Warning("Unable to refresh song list! Exception: " + e); } }
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); } } }
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")) { PluginUI.Instance.OnLoad(); VotingUI.Instance.OnLoad(); if (!PluginConfig.disableSongListTweaks) { SongListTweaks.Instance.OnLoad(); } } }
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 void Refresh() { int removed = queuedSongs.RemoveAll(x => x.songQueueState == SongQueueState.Downloaded || x.songQueueState == SongQueueState.Error); Logger.Log($"Removed {removed} songs from queue"); _queuedSongsTableView.ReloadData(); _queuedSongsTableView.ScrollToRow(0, true); if (queuedSongs.Count(x => x.songQueueState == SongQueueState.Downloading || x.songQueueState == SongQueueState.Queued) == 0) { Logger.Log("All songs downloaded!"); allSongsDownloaded?.Invoke(); } if (queuedSongs.Count(x => x.songQueueState == SongQueueState.Downloading) < PluginConfig.maxSimultaneousDownloads && queuedSongs.Any(x => x.songQueueState == SongQueueState.Queued)) { StartCoroutine(DownloadSong(queuedSongs.First(x => x.songQueueState == SongQueueState.Queued))); } }
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 void AddDefaultPlaylists() { Logger.Log("Creating default playlists..."); List <BeatmapLevelSO> levels = _levelCollection.GetPrivateField <BeatmapLevelSO[]>("_beatmapLevels").ToList(); Playlist _allPlaylist = new Playlist() { playlistTitle = "All songs", playlistAuthor = "", image = Sprites.SpriteToBase64(Sprites.BeastSaberLogo), icon = Sprites.BeastSaberLogo, fileLoc = "" }; _allPlaylist.songs = new List <PlaylistSong>(); _allPlaylist.songs.AddRange(levels.Select(x => new PlaylistSong() { songName = $"{x.songName} {x.songSubName}", level = x, oneSaber = x.beatmapCharacteristics.Any(y => y.characteristicName == "One Saber"), path = "", key = "", levelId = x.levelID, hash = CustomHelpers.CheckHex(x.levelID.Substring(0, Math.Min(32, x.levelID.Length))) })); Logger.Log($"Created \"{_allPlaylist.playlistTitle}\" playlist with {_allPlaylist.songs.Count} songs!"); Playlist _favPlaylist = new Playlist() { playlistTitle = "Your favorite songs", playlistAuthor = "", image = Sprites.SpriteToBase64(Sprites.BeastSaberLogo), icon = Sprites.BeastSaberLogo, fileLoc = "" }; _favPlaylist.songs = new List <PlaylistSong>(); _favPlaylist.songs.AddRange(levels.Where(x => PluginConfig.favoriteSongs.Contains(x.levelID)).Select(x => new PlaylistSong() { songName = $"{x.songName} {x.songSubName}", level = x, oneSaber = x.beatmapCharacteristics.Any(y => y.characteristicName == "One Saber"), path = "", key = "", levelId = x.levelID, hash = CustomHelpers.CheckHex(x.levelID.Substring(0, Math.Min(32, x.levelID.Length))) })); Logger.Log($"Created \"{_favPlaylist.playlistTitle}\" playlist with {_favPlaylist.songs.Count} songs!"); if (PlaylistsCollection.loadedPlaylists.Any(x => x.playlistTitle == "All songs" || x.playlistTitle == "Your favorite songs")) { PlaylistsCollection.loadedPlaylists.RemoveAll(x => x.playlistTitle == "All songs" || x.playlistTitle == "Your favorite songs"); } PlaylistsCollection.loadedPlaylists.Insert(0, _favPlaylist); PlaylistsCollection.loadedPlaylists.Insert(0, _allPlaylist); _favPlaylist.SavePlaylist("Playlists\\favorites.json"); }
public void AddDefaultPlaylists() { Logger.Log("Creating default playlists..."); List <LevelSO> levels = _levelCollection.levels.ToList(); Playlist _allPlaylist = new Playlist() { playlistTitle = "All songs", playlistAuthor = "", image = Base64Sprites.BeastSaberLogoB64, icon = Base64Sprites.BeastSaberLogo, fileLoc = "" }; _allPlaylist.songs = new List <PlaylistSong>(); _allPlaylist.songs.AddRange(levels.Select(x => new PlaylistSong() { songName = $"{x.songName} {x.songSubName}", level = x, oneSaber = x.beatmapCharacteristics.Any(y => y.characteristicName == "One Saber"), path = "", key = "", levelId = x.levelID })); Logger.Log($"Created \"{_allPlaylist.playlistTitle}\" playlist with {_allPlaylist.songs.Count} songs!"); Playlist _favPlaylist = new Playlist() { playlistTitle = "Your favorite songs", playlistAuthor = "", image = Base64Sprites.BeastSaberLogoB64, icon = Base64Sprites.BeastSaberLogo, fileLoc = "" }; _favPlaylist.songs = new List <PlaylistSong>(); _favPlaylist.songs.AddRange(levels.Where(x => PluginConfig.favoriteSongs.Contains(x.levelID)).Select(x => new PlaylistSong() { songName = $"{x.songName} {x.songSubName}", level = x, oneSaber = x.beatmapCharacteristics.Any(y => y.characteristicName == "One Saber"), path = "", key = "", levelId = x.levelID })); Logger.Log($"Created \"{_favPlaylist.playlistTitle}\" playlist with {_favPlaylist.songs.Count} songs!"); if (PlaylistsCollection.loadedPlaylists.Any(x => x.playlistTitle == "All songs" || x.playlistTitle == "Your favorite songs")) { PlaylistsCollection.loadedPlaylists.RemoveAll(x => x.playlistTitle == "All songs" || x.playlistTitle == "Your favorite songs"); } PlaylistsCollection.loadedPlaylists.Insert(0, _favPlaylist); PlaylistsCollection.loadedPlaylists.Insert(0, _allPlaylist); _favPlaylist.SavePlaylist("Playlists\\favorites.json"); }
private void DeletePressed() { IBeatmapLevel level = _detailViewController.selectedDifficultyBeatmap.level; _simpleDialog.Init("Delete song", $"Do you really want to delete \"{ level.songName} {level.songSubName}\"?", "Delete", "Cancel", (selectedButton) => { freePlayFlowCoordinator.InvokePrivateMethod("DismissViewController", new object[] { _simpleDialog, null, false }); if (selectedButton == 0) { try { var levelsTableView = _levelListViewController.GetPrivateField <LevelPackLevelsTableView>("_levelPackLevelsTableView"); List <IPreviewBeatmapLevel> levels = levelsTableView.GetPrivateField <IBeatmapLevelPack>("_pack").beatmapLevelCollection.beatmapLevels.ToList(); int selectedIndex = levels.FindIndex(x => x.levelID == _detailViewController.selectedDifficultyBeatmap.level.levelID); SongDownloader.Instance.DeleteSong(new Song(SongLoader.CustomLevels.First(x => x.levelID == _detailViewController.selectedDifficultyBeatmap.level.levelID))); if (selectedIndex > -1) { int removedLevels = levels.RemoveAll(x => x.levelID == _detailViewController.selectedDifficultyBeatmap.level.levelID); Logger.Log("Removed " + removedLevels + " level(s) from song list!"); _levelListViewController.SetData(CustomHelpers.GetLevelPackWithLevels(levels.Cast <BeatmapLevelSO>().ToArray(), lastPlaylist?.playlistTitle ?? "Custom Songs", lastPlaylist?.icon)); TableView listTableView = levelsTableView.GetPrivateField <TableView>("_tableView"); listTableView.ScrollToCellWithIdx(selectedIndex, TableView.ScrollPositionType.Beginning, false); levelsTableView.SetPrivateField("_selectedRow", selectedIndex); listTableView.SelectCellWithIdx(selectedIndex, true); } } catch (Exception e) { Logger.Error("Unable to delete song! Exception: " + e); } } }); freePlayFlowCoordinator.InvokePrivateMethod("PresentViewController", new object[] { _simpleDialog, null, 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); }
private void _standardLevelResultsViewController_continueButtonPressedEvent(ResultsViewController sender) { try { TableView _levelListTableView = _levelListViewController.GetComponentInChildren <TableView>(); HashSet <int> rows = new HashSet <int>(_levelListTableView.GetPrivateField <HashSet <int> >("_selectedRows")); float scrollPosition = _levelListTableView.GetPrivateField <ScrollRect>("_scrollRect").verticalNormalizedPosition; _levelListTableView.ReloadData(); _levelListTableView.GetPrivateField <ScrollRect>("_scrollRect").verticalNormalizedPosition = scrollPosition; _levelListTableView.SetPrivateField("_targetVerticalNormalizedPosition", scrollPosition); if (rows.Count > 0) { _levelListTableView.SelectRow(rows.First(), true); } }catch (Exception e) { Logger.Warning("Unable to refresh song list! Exception: " + e); } }
public IEnumerator DownloadPlaylist(Playlist playlist) { PlaylistsCollection.MatchSongsForPlaylist(playlist, true); List <PlaylistSong> needToDownload = playlist.songs.Where(x => x.level == null).ToList(); Logger.Log($"Need to download {needToDownload.Count} songs"); _downloadingPlaylist = true; foreach (var item in needToDownload) { Song beatSaverSong = null; if (String.IsNullOrEmpty(playlist.customArchiveUrl)) { Logger.Log("Obtaining hash and url for " + item.key + ": " + item.songName); yield return(GetInfoForSong(playlist, item, (Song song) => { beatSaverSong = song; })); } else { string archiveUrl = playlist.customArchiveUrl.Replace("[KEY]", item.key); beatSaverSong = new Song() { songName = item.songName, id = item.key, downloadingProgress = 0f, hash = (item.levelId == null ? "" : item.levelId), downloadUrl = archiveUrl }; } if (beatSaverSong != null && !SongLoader.CustomLevels.Any(x => x.levelID.Substring(0, 32) == beatSaverSong.hash.ToUpper())) { _downloadQueueViewController.EnqueueSong(beatSaverSong, true); } } _downloadingPlaylist = false; }
private void SceneManager_activeSceneChanged(Scene arg0, Scene arg1) { Logger.Log($"Active scene changed from \"{arg0.name}\" to \"{arg1.name}\""); }
private IEnumerator VoteWithSteamID(bool upvote) { if (!SteamManager.Initialized) { Logger.Error($"SteamManager is not initialized!"); } _upvoteButton.interactable = false; _downvoteButton.interactable = false; Logger.Log($"Getting a ticket..."); var steamId = SteamUser.GetSteamID(); string authTicketHexString = ""; byte[] authTicket = new byte[1024]; var authTicketResult = SteamUser.GetAuthSessionTicket(authTicket, 1024, out var length); if (authTicketResult != HAuthTicket.Invalid) { var beginAuthSessionResult = SteamUser.BeginAuthSession(authTicket, (int)length, steamId); switch (beginAuthSessionResult) { case EBeginAuthSessionResult.k_EBeginAuthSessionResultOK: var result = SteamUser.UserHasLicenseForApp(steamId, new AppId_t(620980)); SteamUser.EndAuthSession(steamId); switch (result) { case EUserHasLicenseForAppResult.k_EUserHasLicenseResultDoesNotHaveLicense: _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "User does not\nhave license"; yield break; case EUserHasLicenseForAppResult.k_EUserHasLicenseResultHasLicense: if (SteamHelper.m_GetAuthSessionTicketResponse == null) { SteamHelper.m_GetAuthSessionTicketResponse = Callback <GetAuthSessionTicketResponse_t> .Create(OnAuthTicketResponse); } SteamHelper.lastTicket = SteamUser.GetAuthSessionTicket(authTicket, 1024, out length); if (SteamHelper.lastTicket != HAuthTicket.Invalid) { Array.Resize(ref authTicket, (int)length); authTicketHexString = BitConverter.ToString(authTicket).Replace("-", ""); } break; case EUserHasLicenseForAppResult.k_EUserHasLicenseResultNoAuth: _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "User is not\nauthenticated"; yield break; } break; default: _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "Auth\nfailed"; yield break; } } Logger.Log("Waiting for Steam callback..."); float startTime = Time.time; yield return(new WaitWhile(() => { return SteamHelper.lastTicketResult != EResult.k_EResultOK && (Time.time - startTime) < 20f; })); if (SteamHelper.lastTicketResult != EResult.k_EResultOK) { Logger.Error($"Auth ticket callback timeout"); _upvoteButton.interactable = true; _downvoteButton.interactable = true; _ratingText.text = "Callback\ntimeout"; yield break; } SteamHelper.lastTicketResult = EResult.k_EResultRevoked; Logger.Log($"Voting..."); Dictionary <string, string> formData = new Dictionary <string, string> (); formData.Add("id", steamId.m_SteamID.ToString()); formData.Add("ticket", authTicketHexString); UnityWebRequest voteWWW = UnityWebRequest.Post($"{PluginConfig.beatsaverURL}/api/songs/voteById/{_lastBeatSaverSong.id}/{(upvote ? 1 : 0)}", formData); voteWWW.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded"); voteWWW.timeout = 30; yield return(voteWWW.SendWebRequest()); if (voteWWW.isNetworkError) { Logger.Error(voteWWW.error); _ratingText.text = voteWWW.error; } else { if (!_firstVote) { yield return(new WaitForSecondsRealtime(2f)); } _firstVote = false; switch (voteWWW.responseCode) { case 200: { JSONNode node = JSON.Parse(voteWWW.downloadHandler.text); _ratingText.text = (int.Parse(node["upVotes"]) - int.Parse(node["downVotes"])).ToString(); if (upvote) { _upvoteButton.interactable = false; _downvoteButton.interactable = true; } else { _downvoteButton.interactable = false; _upvoteButton.interactable = true; } if (!PluginConfig.votedSongs.ContainsKey(_lastLevel.levelID.Substring(0, 32))) { PluginConfig.votedSongs.Add(_lastLevel.levelID.Substring(0, 32), new SongVote(_lastBeatSaverSong.id, upvote ? VoteType.Upvote : VoteType.Downvote)); PluginConfig.SaveConfig(); } else if (PluginConfig.votedSongs[_lastLevel.levelID.Substring(0, 32)].voteType != (upvote ? VoteType.Upvote : VoteType.Downvote)) { PluginConfig.votedSongs[_lastLevel.levelID.Substring(0, 32)] = new SongVote(_lastBeatSaverSong.id, upvote ? VoteType.Upvote : VoteType.Downvote); PluginConfig.SaveConfig(); } }; break; case 500: { _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "Steam API\nerror"; Logger.Error("Error: " + voteWWW.downloadHandler.text); }; break; case 401: { _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "Invalid\nauth ticket"; Logger.Error("Error: " + voteWWW.downloadHandler.text); }; break; case 403: { _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "Steam ID\nmismatch"; Logger.Error("Error: " + voteWWW.downloadHandler.text); }; break; case 400: { _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "Bad\nrequest"; Logger.Error("Error: " + voteWWW.downloadHandler.text); }; break; default: { _upvoteButton.interactable = true; _downvoteButton.interactable = true; _ratingText.text = "Error\n" + voteWWW.responseCode; Logger.Error("Error: " + voteWWW.downloadHandler.text); }; break; } } }
private IEnumerator VoteWithAccessToken(bool upvote) { Logger.Log($"Voting..."); _upvoteButton.interactable = false; _downvoteButton.interactable = false; UnityWebRequest voteWWW = UnityWebRequest.Get($"{PluginConfig.beatsaverURL}/api/songs/vote/{_lastBeatSaverSong.id}/{(upvote ? 1 : 0)}/{PluginConfig.apiAccessToken}"); voteWWW.timeout = 30; yield return(voteWWW.SendWebRequest()); if (voteWWW.isNetworkError) { Logger.Error(voteWWW.error); _ratingText.text = voteWWW.error; } else { if (!_firstVote) { yield return(new WaitForSecondsRealtime(3f)); } _firstVote = false; switch (voteWWW.responseCode) { case 200: { JSONNode node = JSON.Parse(voteWWW.downloadHandler.text); _ratingText.text = (int.Parse(node["upVotes"]) - int.Parse(node["downVotes"])).ToString(); if (upvote) { _upvoteButton.interactable = false; _downvoteButton.interactable = true; } else { _downvoteButton.interactable = false; _upvoteButton.interactable = true; } if (!PluginConfig.votedSongs.ContainsKey(_lastLevel.levelID.Substring(0, 32))) { PluginConfig.votedSongs.Add(_lastLevel.levelID.Substring(0, 32), new SongVote(_lastBeatSaverSong.id, upvote ? VoteType.Upvote : VoteType.Downvote)); PluginConfig.SaveConfig(); } else if (PluginConfig.votedSongs[_lastLevel.levelID.Substring(0, 32)].voteType != (upvote ? VoteType.Upvote : VoteType.Downvote)) { PluginConfig.votedSongs[_lastLevel.levelID.Substring(0, 32)] = new SongVote(_lastBeatSaverSong.id, upvote ? VoteType.Upvote : VoteType.Downvote); PluginConfig.SaveConfig(); } }; break; case 403: { _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "Read-only\ntoken"; }; break; case 401: { _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "Token\nnot found"; }; break; case 400: { _upvoteButton.interactable = false; _downvoteButton.interactable = false; _ratingText.text = "Bad\ntoken"; }; break; default: { _upvoteButton.interactable = true; _downvoteButton.interactable = true; _ratingText.text = "Error\n" + voteWWW.responseCode; }; break; } } }
private void SceneManager_sceneLoaded(Scene to, LoadSceneMode loadMode) { Logger.Log($"Loaded scene \"{to.name}\""); }
private void SetupTweaks() { if (initialized || PluginConfig.disableSongListTweaks) { return; } Logger.Log("Setting up song list tweaks..."); _playlistsFlowCoordinator = (new GameObject("PlaylistsFlowCoordinator")).AddComponent <PlaylistsFlowCoordinator>(); _playlistsFlowCoordinator.didFinishEvent += _playlistsFlowCoordinator_didFinishEvent; _beatmapCharacteristics = Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSO>(); _lastCharacteristic = _beatmapCharacteristics.First(x => x.characteristicName == "Standard"); Resources.FindObjectsOfTypeAll <BeatmapCharacteristicSelectionViewController>().First().didSelectBeatmapCharacteristicEvent += (BeatmapCharacteristicSelectionViewController sender, BeatmapCharacteristicSO selected) => { _lastCharacteristic = selected; }; if (SongLoader.AreSongsLoaded) { _levelCollection = SongLoader.CustomLevelCollectionSO; } else { SongLoader.SongsLoadedEvent += (SongLoader sender, List <CustomLevel> levels) => { _levelCollection = SongLoader.CustomLevelCollectionSO; }; } _mainFlowCoordinator = Resources.FindObjectsOfTypeAll <MainFlowCoordinator>().FirstOrDefault(); _mainFlowCoordinator.GetPrivateField <MainMenuViewController>("_mainMenuViewController").didFinishEvent += SongListTweaks_didFinishEvent; _simpleDialog = ReflectionUtil.GetPrivateField <SimpleDialogPromptViewController>(_mainFlowCoordinator, "_simpleDialogPromptViewController"); _simpleDialog = Instantiate(_simpleDialog.gameObject, _simpleDialog.transform.parent).GetComponent <SimpleDialogPromptViewController>(); _difficultyViewController = Resources.FindObjectsOfTypeAll <BeatmapDifficultyViewController>().FirstOrDefault(); _difficultyViewController.didSelectDifficultyEvent += _difficultyViewController_didSelectDifficultyEvent; _levelListViewController = Resources.FindObjectsOfTypeAll <LevelListViewController>().FirstOrDefault(); _levelListViewController.didSelectLevelEvent += _levelListViewController_didSelectLevelEvent;; RectTransform _tableViewRectTransform = _levelListViewController.GetComponentsInChildren <RectTransform>().First(x => x.name == "TableViewContainer"); _tableViewRectTransform.sizeDelta = new Vector2(0f, -20f); _tableViewRectTransform.anchoredPosition = new Vector2(0f, -2.5f); RectTransform _pageUp = _tableViewRectTransform.GetComponentsInChildren <RectTransform>(true).First(x => x.name == "PageUpButton"); _pageUp.anchoredPosition = new Vector2(0f, -1f); RectTransform _pageDown = _tableViewRectTransform.GetComponentsInChildren <RectTransform>(true).First(x => x.name == "PageDownButton"); _pageDown.anchoredPosition = new Vector2(0f, 1f); _searchButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(-20f, 36.25f), new Vector2(20f, 6f), SearchPressed, "Search"); _searchButton.SetButtonTextSize(3f); _searchButton.ToggleWordWrapping(false); _sortByButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(0f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.SortBy); }, "Sort By"); _sortByButton.SetButtonTextSize(3f); _sortByButton.ToggleWordWrapping(false); _playlistsButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(20f, 36.25f), new Vector2(20f, 6f), PlaylistsButtonPressed, "Playlists"); _playlistsButton.SetButtonTextSize(3f); _playlistsButton.ToggleWordWrapping(false); _defButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(-20f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.Select); SetLevels(_lastCharacteristic, SortMode.Default, ""); }, "Default"); _defButton.SetButtonTextSize(3f); _defButton.ToggleWordWrapping(false); _defButton.gameObject.SetActive(false); _newButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(0f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.Select); SetLevels(_lastCharacteristic, SortMode.Newest, ""); }, "Newest"); _newButton.SetButtonTextSize(3f); _newButton.ToggleWordWrapping(false); _newButton.gameObject.SetActive(false); _authorButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(20f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.Select); SetLevels(_lastCharacteristic, SortMode.Difficulty, ""); }, "Difficulty"); _authorButton.SetButtonTextSize(3f); _authorButton.ToggleWordWrapping(false); _authorButton.gameObject.SetActive(false); _detailViewController = Resources.FindObjectsOfTypeAll <StandardLevelDetailViewController>().First(x => x.name == "StandardLevelDetailViewController"); RectTransform buttonsRect = _detailViewController.GetComponentsInChildren <RectTransform>().First(x => x.name == "Buttons"); buttonsRect.anchoredPosition = new Vector2(0f, 10.75f); RectTransform customButtonsRect = Instantiate(buttonsRect, buttonsRect.parent, true); Destroy(customButtonsRect.GetComponent <ContentSizeFitter>()); Destroy(customButtonsRect.GetComponent <HorizontalLayoutGroup>()); customButtonsRect.name = "CustomUIButtonsHolder"; customButtonsRect.anchoredPosition = new Vector2(0f, 1.25f); _favoriteButton = customButtonsRect.GetComponentsInChildren <Button>().First(x => x.name == "PracticeButton"); _favoriteButton.SetButtonIcon(Base64Sprites.AddToFavorites); _favoriteButton.onClick.AddListener(() => { if (PluginConfig.favoriteSongs.Any(x => x.Contains(_detailViewController.difficultyBeatmap.level.levelID))) { PluginConfig.favoriteSongs.Remove(_detailViewController.difficultyBeatmap.level.levelID); PluginConfig.SaveConfig(); _favoriteButton.SetButtonIcon(Base64Sprites.AddToFavorites); PlaylistsCollection.RemoveLevelFromPlaylist(PlaylistsCollection.loadedPlaylists.First(x => x.playlistTitle == "Your favorite songs"), _detailViewController.difficultyBeatmap.level.levelID); } else { PluginConfig.favoriteSongs.Add(_detailViewController.difficultyBeatmap.level.levelID); PluginConfig.SaveConfig(); _favoriteButton.SetButtonIcon(Base64Sprites.RemoveFromFavorites); PlaylistsCollection.AddSongToPlaylist(PlaylistsCollection.loadedPlaylists.First(x => x.playlistTitle == "Your favorite songs"), new PlaylistSong() { levelId = _detailViewController.difficultyBeatmap.level.levelID, songName = _detailViewController.difficultyBeatmap.level.songName, level = SongDownloader.GetLevel(_detailViewController.difficultyBeatmap.level.levelID) }); } }); _deleteButton = customButtonsRect.GetComponentsInChildren <Button>().First(x => x.name == "PlayButton"); _deleteButton.SetButtonText("Delete"); _deleteButton.ToggleWordWrapping(false); _deleteButton.onClick.AddListener(DeletePressed); _deleteButton.GetComponentsInChildren <RectTransform>().First(x => x.name == "GlowContainer").gameObject.SetActive(false); _deleteButton.interactable = !PluginConfig.disableDeleteButton; //based on https://github.com/halsafar/BeatSaberSongBrowser/blob/master/SongBrowserPlugin/UI/Browser/SongBrowserUI.cs#L192 var statsPanel = _detailViewController.GetComponentsInChildren <CanvasRenderer>(true).First(x => x.name == "LevelParamsPanel"); var statTransforms = statsPanel.GetComponentsInChildren <RectTransform>(); var valueTexts = statsPanel.GetComponentsInChildren <TextMeshProUGUI>().Where(x => x.name == "ValueText").ToList(); foreach (RectTransform r in statTransforms) { if (r.name == "Separator") { continue; } r.sizeDelta = new Vector2(r.sizeDelta.x * 0.85f, r.sizeDelta.y * 0.85f); } var _starStatTransform = Instantiate(statTransforms[1], statsPanel.transform, false); _starStatText = _starStatTransform.GetComponentInChildren <TextMeshProUGUI>(); _starStatTransform.GetComponentInChildren <UnityEngine.UI.Image>().sprite = Base64Sprites.StarFull; _starStatText.text = "--"; initialized = true; }
private void SetupTweaks() { _mainFlowCoordinator = FindObjectOfType <MainFlowCoordinator>(); _mainFlowCoordinator.GetPrivateField <MainMenuViewController>("_mainMenuViewController").didFinishEvent += SongListTweaks_didFinishEvent; RectTransform viewControllersContainer = FindObjectsOfType <RectTransform>().First(x => x.name == "ViewControllers"); if (initialized || PluginConfig.disableSongListTweaks) { return; } Logger.Log("Setting up song list tweaks..."); try { var harmony = HarmonyInstance.Create("BeatSaverDownloaderHarmonyInstance"); harmony.PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception e) { Logger.Log("Unable to patch level list! Exception: " + e); } _playlistsFlowCoordinator = new GameObject("PlaylistsFlowCoordinator").AddComponent <PlaylistsFlowCoordinator>(); _playlistsFlowCoordinator.didFinishEvent += _playlistsFlowCoordinator_didFinishEvent; if (SongLoader.AreSongsLoaded) { _levelCollection = SongLoader.CustomLevelCollectionSO; } else { SongLoader.SongsLoadedEvent += (SongLoader sender, List <CustomLevel> levels) => { _levelCollection = SongLoader.CustomLevelCollectionSO; }; } _simpleDialog = ReflectionUtil.GetPrivateField <SimpleDialogPromptViewController>(_mainFlowCoordinator, "_simpleDialogPromptViewController"); _simpleDialog = Instantiate(_simpleDialog.gameObject, _simpleDialog.transform.parent).GetComponent <SimpleDialogPromptViewController>(); _levelListViewController = viewControllersContainer.GetComponentInChildren <LevelPackLevelsViewController>(true); _levelListViewController.didSelectLevelEvent += _levelListViewController_didSelectLevelEvent; _levelPacksViewController = viewControllersContainer.GetComponentInChildren <LevelPacksViewController>(true); _levelPacksViewController.didSelectPackEvent += _levelPacksViewController_didSelectPackEvent; TableView _songSelectionTableView = _levelListViewController.GetComponentsInChildren <TableView>(true).First(); RectTransform _tableViewRectTransform = _levelListViewController.GetComponentsInChildren <RectTransform>(true).First(x => x.name == "LevelsTableView"); _tableViewRectTransform.sizeDelta = new Vector2(0f, -20.5f); _tableViewRectTransform.anchoredPosition = new Vector2(0f, -2.5f); Button _pageUp = _tableViewRectTransform.GetComponentsInChildren <Button>(true).First(x => x.name == "PageUpButton"); (_pageUp.transform as RectTransform).anchoredPosition = new Vector2(0f, -1f); Button _pageDown = _tableViewRectTransform.GetComponentsInChildren <Button>(true).First(x => x.name == "PageDownButton"); (_pageDown.transform as RectTransform).anchoredPosition = new Vector2(0f, 1f); _fastPageUpButton = Instantiate(_pageUp, _tableViewRectTransform, false); (_fastPageUpButton.transform as RectTransform).anchorMin = new Vector2(0.5f, 1f); (_fastPageUpButton.transform as RectTransform).anchorMax = new Vector2(0.5f, 1f); (_fastPageUpButton.transform as RectTransform).anchoredPosition = new Vector2(-26f, 1f); (_fastPageUpButton.transform as RectTransform).sizeDelta = new Vector2(8f, 6f); _fastPageUpButton.GetComponentsInChildren <RectTransform>().First(x => x.name == "BG").sizeDelta = new Vector2(8f, 6f); _fastPageUpButton.GetComponentsInChildren <UnityEngine.UI.Image>().First(x => x.name == "Arrow").sprite = Sprites.DoubleArrow; _fastPageUpButton.onClick.AddListener(delegate() { FastScrollUp(_songSelectionTableView, PluginConfig.fastScrollSpeed); }); _fastPageDownButton = Instantiate(_pageDown, _tableViewRectTransform, false); (_fastPageDownButton.transform as RectTransform).anchorMin = new Vector2(0.5f, 0f); (_fastPageDownButton.transform as RectTransform).anchorMax = new Vector2(0.5f, 0f); (_fastPageDownButton.transform as RectTransform).anchoredPosition = new Vector2(-26f, -1f); (_fastPageDownButton.transform as RectTransform).sizeDelta = new Vector2(8f, 6f); _fastPageDownButton.GetComponentsInChildren <RectTransform>().First(x => x.name == "BG").sizeDelta = new Vector2(8f, 6f); _fastPageDownButton.GetComponentsInChildren <UnityEngine.UI.Image>().First(x => x.name == "Arrow").sprite = Sprites.DoubleArrow; _fastPageDownButton.onClick.AddListener(delegate() { FastScrollDown(_songSelectionTableView, PluginConfig.fastScrollSpeed); }); _randomButton = Instantiate(viewControllersContainer.GetComponentsInChildren <Button>(true).First(x => x.name == "PracticeButton"), _levelListViewController.rectTransform, false); _randomButton.onClick = new Button.ButtonClickedEvent(); _randomButton.onClick.AddListener(() => { int randomRow = UnityEngine.Random.Range(0, _songSelectionTableView.dataSource.NumberOfCells()); _songSelectionTableView.ScrollToCellWithIdx(randomRow, TableView.ScrollPositionType.Beginning, false); _songSelectionTableView.SelectCellWithIdx(randomRow, true); }); _randomButton.name = "CustomUIButton"; (_randomButton.transform as RectTransform).anchorMin = new Vector2(0.5f, 0.5f); (_randomButton.transform as RectTransform).anchorMax = new Vector2(0.5f, 0.5f); (_randomButton.transform as RectTransform).anchoredPosition = new Vector2(35f, 36.25f); (_randomButton.transform as RectTransform).sizeDelta = new Vector2(8.8f, 6f); _randomButton.SetButtonText(""); _randomButton.SetButtonIcon(Sprites.RandomIcon); _randomButton.GetComponentsInChildren <UnityEngine.UI.Image>().First(x => x.name == "Stroke").sprite = Resources.FindObjectsOfTypeAll <Sprite>().First(x => x.name == "RoundRectSmallStroke"); var _randomIconLayout = _randomButton.GetComponentsInChildren <HorizontalLayoutGroup>().First(x => x.name == "Content"); _randomIconLayout.padding = new RectOffset(0, 0, 0, 0); _searchButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(-20f, 36.25f), new Vector2(20f, 6f), SearchPressed, "Search"); _searchButton.SetButtonTextSize(3f); _searchButton.ToggleWordWrapping(false); _sortByButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(0f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.SortBy); }, "Sort By"); _sortByButton.SetButtonTextSize(3f); _sortByButton.ToggleWordWrapping(false); _playlistsButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(20f, 36.25f), new Vector2(20f, 6f), PlaylistsButtonPressed, "Playlists"); _playlistsButton.SetButtonTextSize(3f); _playlistsButton.ToggleWordWrapping(false); _defButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(-20f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.Select); SetLevels(SortMode.Default, ""); }, "Default"); _defButton.SetButtonTextSize(3f); _defButton.ToggleWordWrapping(false); _defButton.gameObject.SetActive(false); _newButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(0f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.Select); SetLevels(SortMode.Newest, ""); }, "Newest"); _newButton.SetButtonTextSize(3f); _newButton.ToggleWordWrapping(false); _newButton.gameObject.SetActive(false); _difficultyButton = _levelListViewController.CreateUIButton("CreditsButton", new Vector2(20f, 36.25f), new Vector2(20f, 6f), () => { SelectTopButtons(TopButtonsState.Select); SetLevels(SortMode.Difficulty, ""); }, "Difficulty"); _difficultyButton.SetButtonTextSize(3f); _difficultyButton.ToggleWordWrapping(false); _difficultyButton.gameObject.SetActive(false); _detailViewController = viewControllersContainer.GetComponentsInChildren <StandardLevelDetailViewController>(true).First(x => x.name == "LevelDetailViewController"); _detailViewController.didChangeDifficultyBeatmapEvent += _difficultyViewController_didSelectDifficultyEvent; RectTransform buttonsRect = _detailViewController.GetComponentsInChildren <RectTransform>(true).First(x => x.name == "PlayButtons"); _favoriteButton = Instantiate(viewControllersContainer.GetComponentsInChildren <Button>(true).First(x => x.name == "PracticeButton"), buttonsRect, false); _favoriteButton.onClick = new Button.ButtonClickedEvent(); _favoriteButton.onClick.AddListener(() => { if (PluginConfig.favoriteSongs.Any(x => x.Contains(_detailViewController.selectedDifficultyBeatmap.level.levelID))) { PluginConfig.favoriteSongs.Remove(_detailViewController.selectedDifficultyBeatmap.level.levelID); PluginConfig.SaveConfig(); _favoriteButton.SetButtonIcon(Sprites.AddToFavorites); PlaylistsCollection.RemoveLevelFromPlaylist(PlaylistsCollection.loadedPlaylists.First(x => x.playlistTitle == "Your favorite songs"), _detailViewController.selectedDifficultyBeatmap.level.levelID); } else { PluginConfig.favoriteSongs.Add(_detailViewController.selectedDifficultyBeatmap.level.levelID); PluginConfig.SaveConfig(); _favoriteButton.SetButtonIcon(Sprites.RemoveFromFavorites); PlaylistsCollection.AddSongToPlaylist(PlaylistsCollection.loadedPlaylists.First(x => x.playlistTitle == "Your favorite songs"), new PlaylistSong() { levelId = _detailViewController.selectedDifficultyBeatmap.level.levelID, songName = _detailViewController.selectedDifficultyBeatmap.level.songName, level = SongDownloader.GetLevel(_detailViewController.selectedDifficultyBeatmap.level.levelID) }); } }); _favoriteButton.name = "CustomUIButton"; _favoriteButton.SetButtonIcon(Sprites.AddToFavorites); (_favoriteButton.transform as RectTransform).sizeDelta = new Vector2(12f, 8.8f); var _favoriteIconLayout = _favoriteButton.GetComponentsInChildren <HorizontalLayoutGroup>().First(x => x.name == "Content"); _favoriteIconLayout.padding = new RectOffset(3, 3, 0, 0); _favoriteButton.transform.SetAsFirstSibling(); Button practiceButton = buttonsRect.GetComponentsInChildren <Button>().First(x => x.name == "PracticeButton"); (practiceButton.transform as RectTransform).sizeDelta = new Vector2(12f, 8.8f); var _practiceIconLayout = practiceButton.GetComponentsInChildren <HorizontalLayoutGroup>().First(x => x.name == "Content"); _practiceIconLayout.padding = new RectOffset(3, 3, 0, 0); _deleteButton = Instantiate(viewControllersContainer.GetComponentsInChildren <Button>(true).First(x => x.name == "PracticeButton"), buttonsRect, false); _deleteButton.onClick = new Button.ButtonClickedEvent(); _deleteButton.onClick.AddListener(DeletePressed); _deleteButton.name = "CustomUIButton"; _deleteButton.SetButtonIcon(Sprites.DeleteIcon); _deleteButton.interactable = !PluginConfig.disableDeleteButton; (_deleteButton.transform as RectTransform).sizeDelta = new Vector2(8.8f, 8.8f); _deleteButton.GetComponentsInChildren <UnityEngine.UI.Image>().First(x => x.name == "Stroke").sprite = Resources.FindObjectsOfTypeAll <Sprite>().First(x => x.name == "RoundRectSmallStroke"); var _deleteIconLayout = _deleteButton.GetComponentsInChildren <HorizontalLayoutGroup>().First(x => x.name == "Content"); _deleteIconLayout.padding = new RectOffset(0, 0, 1, 1); _deleteButton.transform.SetAsLastSibling(); //based on https://github.com/halsafar/BeatSaberSongBrowser/blob/master/SongBrowserPlugin/UI/Browser/SongBrowserUI.cs#L192 var statsPanel = _detailViewController.GetComponentsInChildren <LevelParamsPanel>(true).First(x => x.name == "LevelParamsPanel"); var statTransforms = statsPanel.GetComponentsInChildren <RectTransform>(true); var valueTexts = statsPanel.GetComponentsInChildren <TextMeshProUGUI>(true).Where(x => x.name == "ValueText").ToList(); foreach (RectTransform r in statTransforms) { if (r.name == "Separator") { continue; } r.sizeDelta = new Vector2(r.sizeDelta.x * 0.85f, r.sizeDelta.y * 0.85f); } var _starStatTransform = Instantiate(statTransforms[1], statsPanel.transform, false); _starStatText = _starStatTransform.GetComponentInChildren <TextMeshProUGUI>(true); _starStatTransform.GetComponentInChildren <UnityEngine.UI.Image>(true).sprite = Sprites.StarFull; _starStatText.text = "--"; ResultsViewController _standardLevelResultsViewController = viewControllersContainer.GetComponentsInChildren <ResultsViewController>(true).First(x => x.name == "StandardLevelResultsViewController"); _standardLevelResultsViewController.continueButtonPressedEvent += _standardLevelResultsViewController_continueButtonPressedEvent; initialized = true; }
//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"); } }
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); } } }
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); }