diff --git a/prefabs/map_info_container.tscn b/prefabs/map_info_container.tscn index bbd365d7..04fbcdcf 100644 --- a/prefabs/map_info_container.tscn +++ b/prefabs/map_info_container.tscn @@ -176,7 +176,7 @@ outline_color = Color(0, 0, 0, 1) shadow_size = 4 shadow_color = Color(0, 0, 0, 1) -[node name="MapInfoContainer" type="Panel" unique_id=150923669] +[node name="MapInfoContainer" type="Panel" unique_id=150923669 node_paths=PackedStringArray("info", "dim", "coverBackground", "cover", "infoSubholder", "mainLabel", "extraLabel", "artistLink", "favoriteButton", "videoButton", "videoDialog", "copyButton", "copyDialog", "deleteButton", "actions", "preview", "speedHolder", "speedPresets", "playHolder", "startButton", "leaderboard", "lbScrollContainer", "lbContainer", "lbExpand", "lbHide")] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 @@ -186,6 +186,31 @@ grow_vertical = 2 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxEmpty_svokg") script = ExtResource("1_50xtp") +info = NodePath("Info") +dim = NodePath("Dim") +coverBackground = NodePath("Info/ScrollContainer/Holder/CoverContainer/Background") +cover = NodePath("Info/ScrollContainer/Holder/CoverContainer/Background/Cover") +infoSubholder = NodePath("Info/ScrollContainer/Holder") +mainLabel = NodePath("Info/ScrollContainer/Holder/Subholder/Main") +extraLabel = NodePath("Info/ScrollContainer/Holder/Subholder/Extra") +artistLink = NodePath("Info/ScrollContainer/Holder/CoverContainer/Background/ArtistLink") +favoriteButton = NodePath("Info/ScrollContainer/Holder/Subholder/Buttons/Favorite") +videoButton = NodePath("Info/ScrollContainer/Holder/Subholder/Buttons/Video") +videoDialog = NodePath("Info/ScrollContainer/Holder/Subholder/Buttons/Video/VideoDialog") +copyButton = NodePath("Info/ScrollContainer/Holder/Subholder/Buttons/Copy") +copyDialog = NodePath("Info/ScrollContainer/Holder/Subholder/Buttons/Copy/CopyDialog") +deleteButton = NodePath("Info/ScrollContainer/Holder/Subholder/Buttons/Delete") +actions = NodePath("Actions") +preview = NodePath("Actions/ScrollContainer/Holder/Preview/AspectRatioContainer/FlatPreview") +speedHolder = NodePath("Actions/ScrollContainer/Holder/Speed") +speedPresets = NodePath("Actions/ScrollContainer/Holder/Speed/ScrollContainer/Presets") +playHolder = NodePath("Actions/ScrollContainer/Holder/Play") +startButton = NodePath("Actions/ScrollContainer/Holder/Play/Button") +leaderboard = NodePath("Leaderboard") +lbScrollContainer = NodePath("Leaderboard/ScrollContainer") +lbContainer = NodePath("Leaderboard/ScrollContainer/VBoxContainer") +lbExpand = NodePath("Leaderboard/Expand") +lbHide = NodePath("LeaderboardHide") [node name="Info" type="Panel" parent="." unique_id=1638277412] layout_mode = 1 @@ -314,7 +339,7 @@ text = "[color=ffffff88]{0} horizontal_alignment = 2 vertical_alignment = 2 -[node name="MainLabel" type="RichTextLabel" parent="Info/ScrollContainer/Holder/Subholder" unique_id=394044659] +[node name="Main" type="RichTextLabel" parent="Info/ScrollContainer/Holder/Subholder" unique_id=394044659] layout_mode = 1 anchors_preset = -1 anchor_right = 1.0 diff --git a/scripts/map/Map.cs b/scripts/map/Map.cs index 4baa45ce..1018e9c2 100644 --- a/scripts/map/Map.cs +++ b/scripts/map/Map.cs @@ -122,24 +122,19 @@ public Map(string filePath, Note[] data = null, string id = null, string artist PrettyTitle = Artist != "" ? $"{Artist} - {Title}" : Title; Rating = rating; Mappers = mappers ?? ["N/A"]; + PrettyMappers = mappers.Join(); CachedMappers = mappers.Join("_"); - PrettyMappers = ""; - Difficulty = difficulty; + Difficulty = Math.Clamp(difficulty, 0, Constants.DIFFICULTIES.Length - 1); DifficultyName = difficultyName?.StripEscapes() ?? Constants.DIFFICULTIES[Difficulty]; AudioBuffer = audioBuffer; CoverBuffer = coverBuffer; VideoBuffer = videoBuffer; Notes = data ?? Array.Empty(); Length = length ?? Notes[^1].Millisecond; - Name = (id.Replace(" ", "_") ?? new Regex("[^a-zA-Z0-9_-]").Replace($"{Mappers.Stringify()}_{PrettyTitle}".Replace(" ", "_"), "")); + Name = id.Replace(" ", "_") ?? new Regex("[^a-zA-Z0-9_-]").Replace($"{Mappers.Stringify()}_{PrettyTitle}".Replace(" ", "_"), ""); AudioExt = (AudioBuffer != null && Encoding.UTF8.GetString(AudioBuffer[0..4]) == "OggS") ? "ogg" : "mp3"; - foreach (string mapper in Mappers) - { - PrettyMappers += $"{mapper}, "; - } - - PrettyMappers = PrettyMappers.Substr(0, PrettyMappers.Length - 2).StripEscapes(); + MapManager.Sanitize(this); } public string EncodeMeta() diff --git a/scripts/map/MapCache.cs b/scripts/map/MapCache.cs index d5640207..29e5a2af 100644 --- a/scripts/map/MapCache.cs +++ b/scripts/map/MapCache.cs @@ -178,6 +178,7 @@ public static int InsertMap(Map map) { var existing = DatabaseService.Connection.Find(x => x.Hash == x.Hash); var updated = DatabaseService.Connection.Find(x => x.Name == map.Name); + try { if (updated != null && existing != null) @@ -276,7 +277,7 @@ public static void OrderAndSetMaps() if (maps.Count < 1) { - MapManager.Maps = new(); + MapManager.Maps = []; return; } @@ -284,6 +285,11 @@ public static void OrderAndSetMaps() sortedMaps.AddRange(maps.Where(x => !x.Favorite).OrderBy(x => x.PrettyTitle)); + foreach (var map in sortedMaps) + { + MapManager.Sanitize(map); + } + MapManager.Maps = sortedMaps; } diff --git a/scripts/map/MapManager.cs b/scripts/map/MapManager.cs index e37beb66..df690414 100644 --- a/scripts/map/MapManager.cs +++ b/scripts/map/MapManager.cs @@ -1,10 +1,7 @@ - -using System; +using System; using System.Collections.Generic; using System.IO; -using System.IO.Compression; using System.Linq; -using System.Security.Cryptography; using System.Threading.Tasks; using Godot; @@ -81,6 +78,7 @@ public static void RemoveVideo(Map map) map.VideoBuffer = null; var oldmap = MapParser.Decode(map.FilePath); + map.Mappers = map.PrettyMappers.Split(" "); map.AudioBuffer = oldmap.AudioBuffer; map.CoverBuffer = oldmap.CoverBuffer; @@ -112,7 +110,6 @@ public static void Delete(Map map) MapCache.RemoveMap(map); Maps.RemoveAll(x => x.Id == map.Id); - Callable.From(() => { _ = ToastNotification.Notify($"Deleted {map.PrettyTitle}!"); @@ -125,5 +122,24 @@ public static void Delete(Map map) } } + public static void Sanitize(Map map) + { + string sanitizedTitle = Util.String.SanitizeZalgo(map.PrettyTitle); + string sanitizedMappers = Util.String.SanitizeZalgo(map.PrettyMappers); + string sanitizedDiffName = Util.String.SanitizeZalgo(map.DifficultyName); + + bool updated = sanitizedTitle != map.PrettyTitle || sanitizedMappers != map.PrettyMappers || sanitizedDiffName != map.DifficultyName; + + if (updated) + { + map.PrettyTitle = sanitizedTitle; + map.PrettyMappers = sanitizedMappers; + map.DifficultyName = sanitizedDiffName; + + Update(map); + Logger.Log($"Sanitized map {map.Name}"); + } + } + public static string MapsFolder => $"{Constants.USER_FOLDER}/maps"; } diff --git a/scripts/ui/menu/play/MapButtonWide.cs b/scripts/ui/menu/play/MapButtonWide.cs index 7fc14377..9aceb00a 100644 --- a/scripts/ui/menu/play/MapButtonWide.cs +++ b/scripts/ui/menu/play/MapButtonWide.cs @@ -45,8 +45,8 @@ public override void UpdateInfo(Map map, bool selected = false) extra.Text = string.Format("[outline_size=2][outline_color=000000][color=808080]{0} — [color={1}]{2} [color=808080]by [color=b0b0b0]{3}", Util.String.FormatTime(map.Length / 1000), Constants.DIFFICULTY_COLORS[map.Difficulty].ToHtml(), - map.DifficultyName, - map.PrettyMappers + Util.String.SanitizeBBCode(map.DifficultyName), + Util.String.SanitizeBBCode(map.PrettyMappers) ); stickoutOffset = selected ? 0.05f : 0; diff --git a/scripts/ui/menu/play/MapInfoContainer.cs b/scripts/ui/menu/play/MapInfoContainer.cs index 6e113f07..410968df 100644 --- a/scripts/ui/menu/play/MapInfoContainer.cs +++ b/scripts/ui/menu/play/MapInfoContainer.cs @@ -13,64 +13,115 @@ public partial class MapInfoContainer : Panel, ISkinnable private readonly PackedScene leaderboardScoreTemplate = ResourceLoader.Load("res://prefabs/score_panel.tscn"); + // Info & main buttons + + [ExportCategory("Info")] + + [Export] private Panel info; + + [Export] + private ColorRect dim; + + [Export] private TextureRect coverBackground; + + [Export] private TextureRect cover; + + [Export] private Panel infoSubholder; + + [Export] private RichTextLabel mainLabel; private string mainLabelFormat; + + [Export] private RichTextLabel extraLabel; private string extraLabelFormat; + + [Export] private LinkPopupButton artistLink; private string artistLinkFormat; - private HBoxContainer mapButtonsContainer; + + [Export] private Button favoriteButton; + + [Export] private Button videoButton; + + [Export] private FileDialog videoDialog; + + [Export] private Button copyButton; + + [Export] private FileDialog copyDialog; + + [Export] private Button deleteButton; + // Actions panel + + [ExportCategory("Actions")] + + [Export] private Panel actions; - private Panel previewHolder; - private Panel modesHolder; - private Panel modifiersHolder; + + [Export] + private FlatPreview preview; + + // [Export] + // private Panel previewHolder; + + // [Export] + // private Panel modesHolder; + + // [Export] + // private Panel modifiersHolder; + + [Export] private Panel speedHolder; + + [Export] private HBoxContainer speedPresets; + + [Export] private Panel playHolder; + + [Export] private Button startButton; + // Leaderboard + + [ExportCategory("Leaderboards")] + + [Export] private Panel leaderboard; + + [Export] private ScrollContainer lbScrollContainer; + + [Export] private VBoxContainer lbContainer; + + [Export] private Button lbExpand; + + [Export] private Button lbHide; - private ColorRect dim; + // Misc + private ShaderMaterial outlineMaterial; public override void _Ready() { - info = GetNode("Info"); - - Panel infoHolder = info.GetNode("ScrollContainer").GetNode("Holder"); - - coverBackground = infoHolder.GetNode("CoverContainer").GetNode("Background"); - cover = coverBackground.GetNode("Cover"); - infoSubholder = infoHolder.GetNode("Subholder"); - mainLabel = infoSubholder.GetNode("MainLabel"); mainLabelFormat = mainLabel.Text; - extraLabel = infoSubholder.GetNode("Extra"); extraLabelFormat = extraLabel.Text; - artistLink = coverBackground.GetNode("ArtistLink"); artistLinkFormat = artistLink.Text; - mapButtonsContainer = infoSubholder.GetNode("Buttons"); - favoriteButton = mapButtonsContainer.GetNode