Example #1
0
        public TableCell CellForIdx(int row)
        {
            LevelListTableCell cell = Instantiate(_songTableCellInstance);

            cell.reuseIdentifier = "SongCell";
            cell.GetField <UnityEngine.UI.Image>("_coverImage").sprite = availableFiles[row].CoverImage;
            cell.GetField <TextMeshProUGUI>("_songNameText").text      = availableFiles[row].FileName;
            cell.GetField <TextMeshProUGUI>("_authorText").text        = "";

            cell.SetField("_beatmapCharacteristicAlphas", new float[0]);
            cell.SetField("_beatmapCharacteristicImages", new UnityEngine.UI.Image[0]);
            cell.SetField("_bought", true);

            return(cell);
        }
        public void Init(LevelListTableCell originalTableCell)
        {
            _backgroundImage = transform.Find("Background").GetComponent <ImageView>();
            _nameText        = transform.Find("SongName").GetComponent <CurvedTextMeshPro>();
            _authorText      = transform.Find("SongAuthor").GetComponent <CurvedTextMeshPro>();
            _cover           = transform.Find("CoverImage").GetComponent <ImageView>();

            _nameText.richText   = false;
            _authorText.richText = false;

            _nameText.name   = "AvatarName";
            _authorText.name = "AvatarAuthor";

            _wasPressedSignal = originalTableCell.GetField <Signal, SelectableCell>("_wasPressedSignal");
        }
Example #3
0
        ////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Get new table cell or reuse old one
        /// </summary>
        /// <returns></returns>
        private LevelListTableCell GetTableCell()
        {
            LevelListTableCell l_Cell = (LevelListTableCell)TableViewInstance.DequeueReusableCellForIdentifier("BSP_SongList_Cell");

            if (!l_Cell)
            {
                if (m_SongListTableCellInstance == null)
                {
                    m_SongListTableCellInstance = UnityEngine.Resources.FindObjectsOfTypeAll <LevelListTableCell>().First(x => (x.name == "LevelListTableCell"));
                }

                l_Cell = Instantiate(m_SongListTableCellInstance);
            }

            l_Cell.SetField("_notOwned", false);
            l_Cell.reuseIdentifier = "BSP_SongList_Cell";

            if (m_DefaultCover == null)
            {
                m_DefaultCover = l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite;
            }

            return(l_Cell);
        }
Example #4
0
        private async void SetDataFromLevelAsync(SongRequest request, LevelListTableCell _tableCell, int row)
        {
            var favouritesBadge = _tableCell.GetField <Image, LevelListTableCell>("_favoritesBadgeImage");

            favouritesBadge.enabled = false;

            var highlight = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');

            var msg = highlight ? "MSG" : "";

            var hasMessage  = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');
            var isChallenge = request.requestInfo.IndexOf("!challenge", StringComparison.OrdinalIgnoreCase) >= 0;

            var pp      = "";
            var ppvalue = request.song["pp"].AsInt;

            if (ppvalue > 0)
            {
                pp = $" {ppvalue} PP";
            }

            var dt = new RequestBot.DynamicText().AddSong(request.song).AddUser(ref request.requestor); // Get basic fields

            dt.Add("Status", request.status.ToString());
            dt.Add("Info", (request.requestInfo != "") ? " / " + request.requestInfo : "");
            dt.Add("RequestTime", request.requestTime.ToLocalTime().ToString("hh:mm"));

            var songDurationText = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText");

            songDurationText.text = request.song["songlength"].Value;

            var songBpm = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText");

            (songBpm.transform as RectTransform).anchoredPosition = new Vector2(-2.5f, -1.8f);
            (songBpm.transform as RectTransform).sizeDelta       += new Vector2(15f, 0f);

            var k = new List <string>();

            if (hasMessage)
            {
                k.Add("MSG");
            }
            if (isChallenge)
            {
                k.Add("VS");
            }
            k.Add(request.song["id"]);
            songBpm.text = string.Join(" - ", k);

            var songBmpIcon = _tableCell.GetComponentsInChildren <Image>().LastOrDefault(c => string.Equals(c.name, "BpmIcon", StringComparison.OrdinalIgnoreCase));

            if (songBmpIcon != null)
            {
                Destroy(songBmpIcon);
            }

            var songName = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songNameText");

            songName.richText = true;
            songName.text     = $"{request.song["songName"].Value} <size=50%>{RequestBot.GetRating(ref request.song)} <color=#3fff3f>{pp}</color></size>";

            var author = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songAuthorText");

            author.richText = true;
            author.text     = dt.Parse(RequestBot.QueueListRow2);

            var image    = _tableCell.GetField <Image, LevelListTableCell>("_coverImage");
            var imageSet = false;

            if (SongCore.Loader.AreSongsLoaded)
            {
                var level = CustomLevelForRow(row);
                if (level != null)
                {
                    // set image from song's cover image
                    var sprite = await level.GetCoverImageAsync(System.Threading.CancellationToken.None);

                    image.sprite = sprite;
                    imageSet     = true;
                }
            }

            if (!imageSet)
            {
                var url = request.song["coverURL"].Value;

                if (!_cachedTextures.TryGetValue(url, out var tex))
                {
                    var b = await Plugin.WebClient.DownloadImage($"{url}", System.Threading.CancellationToken.None);

                    tex = new Texture2D(2, 2);
                    tex.LoadImage(b);

                    try
                    {
                        _cachedTextures.Add(url, tex);
                    }
                    catch (Exception)
                    {
                        // ignored
                    }
                }

                image.sprite = Base64Sprites.Texture2DToSprite(tex);
            }

            UIHelper.AddHintText(_tableCell.transform as RectTransform, dt.Parse(RequestBot.SongHintText));
        }
Example #5
0
        ////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Build cell
        /// </summary>
        /// <param name="p_TableView">Table view instance</param>
        /// <param name="p_Index">Cell index</param>
        /// <returns></returns>
        public HMUI.TableCell CellForIdx(HMUI.TableView p_TableView, int p_Index)
        {
            LevelListTableCell l_Cell = GetTableCell();

            TextMeshProUGUI l_Text    = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songNameText");
            TextMeshProUGUI l_SubText = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songAuthorText");

            l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_favoritesBadgeImage").gameObject.SetActive(false);

            var l_HoverHint = l_Cell.gameObject.GetComponent <HMUI.HoverHint>();

            if (l_HoverHint == null || !l_HoverHint)
            {
                l_HoverHint = l_Cell.gameObject.AddComponent <HMUI.HoverHint>();
                l_HoverHint.SetField("_hoverHintController", UnityEngine.Resources.FindObjectsOfTypeAll <HMUI.HoverHintController>().First());
            }

            if (l_Cell.gameObject.GetComponent <LocalizedHoverHint>())
            {
                UnityEngine.GameObject.Destroy(l_Cell.gameObject.GetComponent <LocalizedHoverHint>());
            }

            var l_SongEntry = Data[p_Index];

            l_SongEntry.Init();

            if ((l_SongEntry.BeatSaver_Map != null && !l_SongEntry.BeatSaver_Map.Partial) || l_SongEntry.CustomLevel != null)
            {
                var l_HaveSong = l_SongEntry.CustomLevel != null && SongCore.Loader.CustomLevels.ContainsKey(l_SongEntry.CustomLevel.customLevelPath);

                string l_MapName       = "";
                string l_MapAuthor     = "";
                string l_MapSongAuthor = "";
                float  l_Duration      = 0f;
                float  l_BPM           = 0f;

                if (l_SongEntry.CustomLevel != null)
                {
                    l_MapName       = l_SongEntry.CustomLevel.songName;
                    l_MapAuthor     = l_SongEntry.CustomLevel.levelAuthorName;
                    l_MapSongAuthor = l_SongEntry.CustomLevel.songAuthorName;
                    l_BPM           = l_SongEntry.CustomLevel.beatsPerMinute;
                    l_Duration      = l_SongEntry.CustomLevel.songDuration;
                }
                else
                {
                    var l_FirstDiff = l_SongEntry.BeatSaver_Map.Metadata.Characteristics.First().Difficulties.Where(x => x.Value.HasValue).LastOrDefault();

                    l_MapName       = l_SongEntry.BeatSaver_Map.Name;
                    l_MapAuthor     = l_SongEntry.BeatSaver_Map.Metadata.LevelAuthorName;
                    l_MapSongAuthor = l_SongEntry.BeatSaver_Map.Metadata.SongAuthorName;
                    l_BPM           = l_SongEntry.BeatSaver_Map.Metadata.BPM;
                    l_Duration      = l_FirstDiff.Value.Value.Length;
                }

                string l_Title    = l_SongEntry.TitlePrefix + (l_SongEntry.TitlePrefix.Length != 0 ? " " : "") + (l_HaveSong ? "<#7F7F7F>" : "") + l_MapName;
                string l_SubTitle = l_MapAuthor + " [" + l_MapSongAuthor + "]";

                if (l_Title.Length > (28 + (l_HaveSong ? "<#7F7F7F>".Length : 0)))
                {
                    l_Title = l_Title.Substring(0, 28 + (l_HaveSong ? "<#7F7F7F>".Length : 0)) + "...";
                }
                if (l_SubTitle.Length > 28)
                {
                    l_SubTitle = l_SubTitle.Substring(0, 28) + "...";
                }

                l_Text.text    = l_Title;
                l_SubText.text = l_SubTitle;

                var l_BPMText = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText");
                l_BPMText.gameObject.SetActive(true);
                l_BPMText.text = ((int)l_BPM).ToString();

                var l_DurationText = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText");
                l_DurationText.gameObject.SetActive(true);
                l_DurationText.text = l_Duration >= 0.0 ? $"{Math.Floor((double)l_Duration / 60):N0}:{Math.Floor((double)l_Duration % 60):00}" : "--";

                l_Cell.transform.Find("BpmIcon").gameObject.SetActive(true);

                if (l_SongEntry.Cover != null)
                {
                    l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover;
                }
                else if (CoverCache.TryGetValue(l_SongEntry.GetLevelHash(), out var l_Cover))
                {
                    l_SongEntry.Cover = l_Cover;
                    l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover;

                    OnCoverFetched?.Invoke(l_Cell.idx, l_SongEntry);
                }
                else
                {
                    l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = m_DefaultCover;

                    if (l_HaveSong)
                    {
                        var l_CoverTask = l_SongEntry.CustomLevel.GetCoverImageAsync(CancellationToken.None);
                        _ = l_CoverTask.ContinueWith(p_CoverTaskResult =>
                        {
                            if (l_Cell.idx >= Data.Count || l_SongEntry != Data[l_Cell.idx])
                            {
                                return;
                            }

                            Unity.MainThreadInvoker.Enqueue(() =>
                            {
                                /// Update infos
                                l_SongEntry.Cover = p_CoverTaskResult.Result;

                                /// Cache cover
                                if (!CoverCache.ContainsKey(l_SongEntry.GetLevelHash()))
                                {
                                    CoverCache.Add(l_SongEntry.GetLevelHash(), l_SongEntry.Cover);
                                }

                                if (l_Cell.idx < Data.Count && l_SongEntry == Data[l_Cell.idx])
                                {
                                    l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover;
                                    l_Cell.RefreshVisuals();

                                    OnCoverFetched?.Invoke(l_Cell.idx, l_SongEntry);
                                }
                            });
                        });
                    }
                    else if (l_SongEntry.BeatSaver_Map != null)
                    {
                        /// Fetch cover
                        var l_CoverTask = l_SongEntry.BeatSaver_Map.FetchCoverImage();
                        _ = l_CoverTask.ContinueWith(p_CoverTaskResult =>
                        {
                            if (l_Cell.idx >= Data.Count || l_SongEntry != Data[l_Cell.idx])
                            {
                                return;
                            }

                            Unity.MainThreadInvoker.Enqueue(() =>
                            {
                                var l_Texture = Unity.Texture2D.CreateFromRaw(p_CoverTaskResult.Result);
                                if (l_Texture != null)
                                {
                                    l_SongEntry.Cover = UnityEngine.Sprite.Create(l_Texture, new UnityEngine.Rect(0, 0, l_Texture.width, l_Texture.height), new UnityEngine.Vector2(0.5f, 0.5f), 100);

                                    /// Cache cover
                                    if (!CoverCache.ContainsKey(l_SongEntry.GetLevelHash()))
                                    {
                                        CoverCache.Add(l_SongEntry.GetLevelHash(), l_SongEntry.Cover);
                                    }

                                    if (l_Cell.idx < Data.Count && l_SongEntry == Data[l_Cell.idx])
                                    {
                                        l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover;
                                        l_Cell.RefreshVisuals();

                                        OnCoverFetched?.Invoke(l_Cell.idx, l_SongEntry);
                                    }
                                }
                            });
                        });
                    }
                }
            }
            else if (l_SongEntry.BeatSaver_Map != null && l_SongEntry.BeatSaver_Map.Partial)
            {
                l_Text.text    = "Loading from BeatSaver...";
                l_SubText.text = "";

                l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText").gameObject.SetActive(false);
                l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText").gameObject.SetActive(false);
                l_Cell.transform.Find("BpmIcon").gameObject.SetActive(false);

                l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = m_DefaultCover;
            }
            else
            {
                l_Text.text    = "<#FF0000>Invalid song";
                l_SubText.text = l_SongEntry.CustomLevel != null?l_SongEntry.CustomLevel.levelID.Replace("custom_level_", "") : "";

                l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText").gameObject.SetActive(false);
                l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText").gameObject.SetActive(false);
                l_Cell.transform.Find("BpmIcon").gameObject.SetActive(false);

                l_Cell.GetField <UnityEngine.UI.Image, LevelListTableCell>("_coverImage").sprite = m_DefaultCover;
            }

            if (!string.IsNullOrEmpty(l_SongEntry.HoverHint))
            {
                var l_HoverHintText = l_SongEntry.HoverHint;
                if (l_SongEntry.HoverHintTimeArg.HasValue && l_HoverHintText.Contains("$$time$$"))
                {
                    var l_Replace = "";
                    var l_Elapsed = Misc.Time.UnixTimeNow() - Misc.Time.ToUnixTime(l_SongEntry.HoverHintTimeArg.Value);
                    if (l_Elapsed < (60 * 60))
                    {
                        l_Replace = Math.Max(1, l_Elapsed / 60).ToString() + " minute(s) ago";
                    }
                    else if (l_Elapsed < (60 * 60 * 24))
                    {
                        l_Replace = Math.Max(1, l_Elapsed / (60 * 60)).ToString() + " hour(s) ago";
                    }
                    else
                    {
                        l_Replace = Math.Max(1, l_Elapsed / (60 * 60 * 24)).ToString() + " day(s) ago";
                    }

                    l_HoverHintText = l_HoverHintText.Replace("$$time$$", l_Replace);
                }

                l_HoverHint.enabled = true;
                l_HoverHint.text    = l_HoverHintText;
            }
            else
            {
                l_HoverHint.enabled = false;
            }

            return(l_Cell);
        }
Example #6
0
        ////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Build cell
        /// </summary>
        /// <param name="p_TableView">Table view instance</param>
        /// <param name="p_Index">Cell index</param>
        /// <returns></returns>
        public TableCell CellForIdx(TableView p_TableView, int p_Index)
        {
            LevelListTableCell l_Cell = GetTableCell();

            TextMeshProUGUI l_Text    = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songNameText");
            TextMeshProUGUI l_SubText = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songAuthorText");

            l_Cell.GetField <Image, LevelListTableCell>("_favoritesBadgeImage").gameObject.SetActive(false);

            var l_HoverHint = l_Cell.gameObject.GetComponent <HoverHint>();

            if (l_HoverHint == null || !l_HoverHint)
            {
                l_HoverHint = l_Cell.gameObject.AddComponent <HoverHint>();
                l_HoverHint.SetField("_hoverHintController", Resources.FindObjectsOfTypeAll <HoverHintController>().First());
            }

            if (l_Cell.gameObject.GetComponent <LocalizedHoverHint>())
            {
                GameObject.Destroy(l_Cell.gameObject.GetComponent <LocalizedHoverHint>());
            }

            var l_SongEntry = Data[p_Index];

            if (!l_SongEntry.BeatMap.Partial)
            {
                var l_LocalSong = SongCore.Loader.GetLevelByHash(l_SongEntry.BeatMap.Hash);
                l_Text.text    = l_SongEntry.NamePrefix + (l_SongEntry.NamePrefix.Length != 0 ? " " : "") + ((l_LocalSong != null && SongCore.Loader.CustomLevels.ContainsKey(l_LocalSong.customLevelPath)) ? "<#7F7F7F>" : "") + l_SongEntry.BeatMap.Name;
                l_SubText.text = l_SongEntry.BeatMap.Metadata.SongAuthorName + " [" + l_SongEntry.BeatMap.Metadata.LevelAuthorName + "]";

                if (l_Text.text.Length > (28 + (l_LocalSong != null ? "<#7F7F7F>".Length : 0)))
                {
                    l_Text.text = l_Text.text.Substring(0, 28 + (l_LocalSong != null ? "<#7F7F7F>".Length : 0)) + "...";
                }
                if (l_SubText.text.Length > 28)
                {
                    l_SubText.text = l_SubText.text.Substring(0, 28) + "...";
                }

                var l_FirstDiff = l_SongEntry.BeatMap.Metadata.Characteristics.First().Difficulties.Where(x => x.Value.HasValue).LastOrDefault();

                var l_BPMText = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText");
                l_BPMText.gameObject.SetActive(true);
                l_BPMText.text = ((int)l_SongEntry.BeatMap.Metadata.BPM).ToString();

                var l_DurationText = l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText");
                l_DurationText.gameObject.SetActive(true);
                l_DurationText.text = l_FirstDiff.Value.Value.Length >= 0.0 ? $"{Math.Floor((double)l_FirstDiff.Value.Value.Length / 60):N0}:{Math.Floor((double)l_FirstDiff.Value.Value.Length % 60):00}" : "--";

                l_Cell.transform.Find("BpmIcon").gameObject.SetActive(true);

                if (l_SongEntry.Cover != null)
                {
                    l_Cell.GetField <Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover;
                }
                else
                {
                    l_Cell.GetField <Image, LevelListTableCell>("_coverImage").sprite = m_DefaultCover;

                    /// Fetch cover
                    var l_CoverTask = l_SongEntry.BeatMap.FetchCoverImage();
                    _ = l_CoverTask.ContinueWith(p_CoverTaskResult =>
                    {
                        if (l_Cell.idx >= Data.Count || l_SongEntry.BeatMap.Hash != Data[l_Cell.idx].BeatMap.Hash)
                        {
                            return;
                        }

                        HMMainThreadDispatcher.instance.Enqueue(() =>
                        {
                            var l_Texture = new Texture2D(2, 2);

                            if (l_Texture.LoadImage(p_CoverTaskResult.Result))
                            {
                                l_SongEntry.Cover = Sprite.Create(l_Texture, new Rect(0, 0, l_Texture.width, l_Texture.height), new Vector2(0.5f, 0.5f), 100);

                                if (l_Cell.idx < Data.Count && l_SongEntry.BeatMap.Hash == Data[l_Cell.idx].BeatMap.Hash)
                                {
                                    l_Cell.GetField <Image, LevelListTableCell>("_coverImage").sprite = l_SongEntry.Cover;
                                }
                            }
                        });
                    });
                }
            }
            else
            {
                l_Text.text    = "Loading from BeatSaver...";
                l_SubText.text = "";

                l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songBpmText").gameObject.SetActive(false);
                l_Cell.GetField <TextMeshProUGUI, LevelListTableCell>("_songDurationText").gameObject.SetActive(false);
                l_Cell.transform.Find("BpmIcon").gameObject.SetActive(false);

                l_Cell.GetField <Image, LevelListTableCell>("_coverImage").sprite = m_DefaultCover;
            }

            l_HoverHint.text = "Requested by <u>" + l_SongEntry.RequesterName + "</u>";

            return(l_Cell);
        }
        private async void SetDataFromLevelAsync(SongRequest request, LevelListTableCell _tableCell, int row)
        {
            var favouritesBadge = _tableCell.GetField <RawImage, LevelListTableCell>("_favoritesBadgeImage");

            favouritesBadge.enabled = false;

            bool highlight = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');

            string msg = highlight ? "MSG" : "";

            var hasMessage  = (request.requestInfo.Length > 0) && (request.requestInfo[0] == '!');
            var isChallenge = request.requestInfo.IndexOf("!challenge", StringComparison.OrdinalIgnoreCase) >= 0;

            var beatmapCharacteristicImages = _tableCell.GetField <UnityEngine.UI.Image[], LevelListTableCell>("_beatmapCharacteristicImages"); // NEW VERSION

            foreach (var i in beatmapCharacteristicImages)
            {
                i.enabled = false;
            }

            // causing a nullex?
            //_tableCell.SetField("_beatmapCharacteristicAlphas", new float[5] { 1f, 1f, 1f, 1f, 1f });

            // set message icon if request has a message // NEW VERSION
            if (hasMessage)
            {
                beatmapCharacteristicImages.Last().sprite  = Base64Sprites.InfoIcon;
                beatmapCharacteristicImages.Last().enabled = true;
            }

            // set challenge icon if song is a challenge
            if (isChallenge)
            {
                var el = beatmapCharacteristicImages.ElementAt(beatmapCharacteristicImages.Length - 2);

                el.sprite  = Base64Sprites.VersusChallengeIcon;
                el.enabled = true;
            }

            string pp      = "";
            int    ppvalue = request.song["pp"].AsInt;

            if (ppvalue > 0)
            {
                pp = $" {ppvalue} PP";
            }

            var dt = new RequestBot.DynamicText().AddSong(request.song).AddUser(ref request.requestor); // Get basic fields

            dt.Add("Status", request.status.ToString());
            dt.Add("Info", (request.requestInfo != "") ? " / " + request.requestInfo : "");
            dt.Add("RequestTime", request.requestTime.ToLocalTime().ToString("hh:mm"));

            var songName = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_songNameText");

            //songName.text = $"{request.song["songName"].Value} <size=50%>{RequestBot.GetRating(ref request.song)} <color=#3fff3f>{pp}</color></size> <color=#ff00ff>{msg}</color>";
            songName.text = $"{request.song["songName"].Value} <size=50%>{RequestBot.GetRating(ref request.song)} <color=#3fff3f>{pp}</color></size>"; // NEW VERSION

            var author = _tableCell.GetField <TextMeshProUGUI, LevelListTableCell>("_authorText");

            author.text = dt.Parse(RequestBot.QueueListRow2);

            var image    = _tableCell.GetField <RawImage, LevelListTableCell>("_coverRawImage");
            var imageSet = false;

            if (SongCore.Loader.AreSongsLoaded)
            {
                CustomPreviewBeatmapLevel level = CustomLevelForRow(row);
                if (level != null)
                {
                    //Plugin.Log("custom level found");
                    // set image from song's cover image
                    var tex = await level.GetCoverImageTexture2DAsync(System.Threading.CancellationToken.None);

                    image.texture = tex;
                    imageSet      = true;
                }
            }

            if (!imageSet)
            {
                string url = request.song["coverURL"].Value;

                if (!_cachedTextures.TryGetValue(url, out var tex))
                {
                    var b = await Plugin.WebClient.DownloadImage($"https://beatsaver.com{url}", System.Threading.CancellationToken.None);

                    tex = new Texture2D(2, 2);
                    tex.LoadImage(b);

                    try
                    {
                        _cachedTextures.Add(url, tex);
                    }
                    catch (Exception)
                    {
                    }
                }

                image.texture = tex;
            }

            UIHelper.AddHintText(_tableCell.transform as RectTransform, dt.Parse(RequestBot.SongHintText));
        }