From f7e533506c9b11beff9f6ac133b5d8a98773cb09 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Mon, 22 Jun 2026 19:53:34 -0400 Subject: [PATCH 01/23] export button --- prefabs/map_info_container.tscn | 15 +++- scripts/map/MapParser.cs | 71 ++++++++++++++++++ scripts/ui/menu/play/MapInfoContainer.cs | 17 +++++ user/skins/default/ui/buttons/export.png | Bin 0 -> 2246 bytes .../default/ui/buttons/export.png.import | 40 ++++++++++ 5 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 user/skins/default/ui/buttons/export.png create mode 100644 user/skins/default/ui/buttons/export.png.import diff --git a/prefabs/map_info_container.tscn b/prefabs/map_info_container.tscn index 98ccc0ce..b6d30a81 100644 --- a/prefabs/map_info_container.tscn +++ b/prefabs/map_info_container.tscn @@ -6,6 +6,7 @@ [ext_resource type="Theme" uid="uid://dhuhu3mmaew1a" path="res://themes/theme.tres" id="4_4d08m"] [ext_resource type="Script" uid="uid://c1235cyjfh4rl" path="res://scripts/ui/LinkPopupButton.cs" id="4_dccrs"] [ext_resource type="Texture2D" uid="uid://7px5v8ikildx" path="res://user/skins/default/ui/buttons/favorite.png" id="5_1m5pv"] +[ext_resource type="Texture2D" uid="uid://dkpbociv8fgfd" path="res://user/skins/default/ui/buttons/export.png" id="5_g02bu"] [ext_resource type="Script" uid="uid://dy45uerqy0yd7" path="res://scripts/ui/FlatPreview.cs" id="5_svokg"] [ext_resource type="Texture2D" uid="uid://degvlg4p0if70" path="res://user/skins/default/ui/buttons/add_video.png" id="6_g02bu"] [ext_resource type="Texture2D" uid="uid://cgxbwx4f28lt2" path="res://user/skins/default/ui/buttons/copy.png" id="7_oibm8"] @@ -175,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_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")] +[node name="MapInfoContainer" type="Panel" unique_id=150923669 node_paths=PackedStringArray("info", "dim", "coverBackground", "cover", "infoSubholder", "mainLabel", "extraLabel", "artistLink", "exportButton", "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 @@ -193,6 +194,7 @@ infoSubholder = NodePath("Info/ScrollContainer/HBoxContainer") mainLabel = NodePath("Info/ScrollContainer/HBoxContainer/Subholder/Main") extraLabel = NodePath("Info/ScrollContainer/HBoxContainer/Subholder/Extra") artistLink = NodePath("Info/ScrollContainer/HBoxContainer/Background/ArtistLink") +exportButton = NodePath("Info/ScrollContainer/HBoxContainer/Subholder/Buttons/Export") favoriteButton = NodePath("Info/ScrollContainer/HBoxContainer/Subholder/Buttons/Favorite") videoButton = NodePath("Info/ScrollContainer/HBoxContainer/Subholder/Buttons/Video") videoDialog = NodePath("Info/ScrollContainer/HBoxContainer/Subholder/Buttons/Video/VideoDialog") @@ -357,6 +359,17 @@ grow_horizontal = 0 grow_vertical = 0 alignment = 2 +[node name="Export" type="Button" parent="Info/ScrollContainer/HBoxContainer/Subholder/Buttons" unique_id=2033571562] +layout_mode = 2 +tooltip_text = "Export (Shift+Click for .sspm export)" +focus_mode = 0 +mouse_default_cursor_shape = 2 +theme = ExtResource("4_4d08m") +theme_override_colors/font_color = Color(1, 1, 1, 1) +theme_override_constants/icon_max_width = 24 +icon = ExtResource("5_g02bu") +icon_alignment = 1 + [node name="Favorite" type="Button" parent="Info/ScrollContainer/HBoxContainer/Subholder/Buttons" unique_id=1022164792] layout_mode = 2 tooltip_text = "Favorite" diff --git a/scripts/map/MapParser.cs b/scripts/map/MapParser.cs index c1fc5f92..2459ac7d 100644 --- a/scripts/map/MapParser.cs +++ b/scripts/map/MapParser.cs @@ -67,6 +67,77 @@ await Task.Run(() => if (notify) ToastNotification.Notify($"Finished importing {files.Length} map(s)"); } + public static void ExportEncode(Map map) + { + string exportPath = $"{Constants.USER_FOLDER}/export/"; + string exportFilePath = Path.Combine(exportPath, $"{map.Name}.phxm"); + + if (!Directory.Exists(exportPath)) Directory.CreateDirectory(exportPath); + + /* + uint32; ms + 1 byte; quantum + 1 byte OR int32; x + 1 byte OR int32; y + */ + + using var ms = new MemoryStream(); + using (var archive = new ZipArchive(ms, ZipArchiveMode.Create)) + { + var metadata = archive.CreateEntry("metadata.json", CompressionLevel.NoCompression); + using (var writer = new StreamWriter(metadata.Open())) + writer.Write(map.EncodeMeta()); + var objects = archive.CreateEntry("objects.phxmo", CompressionLevel.NoCompression); + using (var objs = objects.Open()) + { + using BinaryWriter bw = new BinaryWriter(objs); + bw.Write((uint)12); + bw.Write((uint)map.Notes.Length); + foreach (var note in map.Notes) + { + bool quantum = (int)note.X != note.X || (int)note.Y != note.Y || note.X < -1 || note.X > 1 || note.Y < -1 || note.Y > 1; + bw.Write((uint)note.Millisecond); + bw.Write(Convert.ToByte(quantum)); + if (quantum) + { + bw.Write((float)note.X); + bw.Write((float)note.Y); + } + else + { + bw.Write((byte)(note.X + 1)); + bw.Write((byte)(note.Y + 1)); + } + } + bw.Write(0); // timing point count + bw.Write(0); // brightness count + bw.Write(0); // contrast count + bw.Write(0); // saturation count + bw.Write(0); // blur count + bw.Write(0); // fov count + bw.Write(0); // tint count + bw.Write(0); // position count + bw.Write(0); // rotation count + bw.Write(0); // ar factor count + bw.Write(0); // text count + } + + void addAsset(string name, byte[] buffer) + { + var asset = archive.CreateEntry(name, CompressionLevel.NoCompression); + using var stream = asset.Open(); + stream.Write(buffer, 0, buffer.Length); + } + + if (map.AudioBuffer != null) addAsset($"audio.{map.AudioExt}", map.AudioBuffer); + if (map.CoverBuffer != null) addAsset($"cover.png", map.CoverBuffer); + if (map.VideoBuffer != null) addAsset($"video.mp4", map.VideoBuffer); + } + + map.Hash = Convert.ToHexString(MD5.HashData(ms.ToArray())).ToLower(); + File.WriteAllBytes(exportFilePath, ms.ToArray()); + } + public static void Encode(Map map, bool logBenchmark = false) { double start = Time.GetTicksUsec(); diff --git a/scripts/ui/menu/play/MapInfoContainer.cs b/scripts/ui/menu/play/MapInfoContainer.cs index 8611ee9b..364a2afb 100644 --- a/scripts/ui/menu/play/MapInfoContainer.cs +++ b/scripts/ui/menu/play/MapInfoContainer.cs @@ -44,6 +44,9 @@ public partial class MapInfoContainer : Panel, ISkinnable private LinkPopupButton artistLink; private string artistLinkFormat; + [Export] + private Button exportButton; + [Export] private Button favoriteButton; @@ -123,6 +126,20 @@ public override void _Ready() artistLinkFormat = artistLink.Text; outlineMaterial = info.GetNode("Outline").Material as ShaderMaterial; + exportButton.Pressed += () => + { + string exportPath = $"{Constants.USER_FOLDER}/export/"; + string exportFilePath = Path.Combine(exportPath, $"{Map.Name}.phxm"); + + _ = ToastNotification.Notify($"Exporting to {exportFilePath}", 1); + MapParser.ExportEncode(Map); + + _ = ToastNotification.Notify($"Done! Opening export folder...", 0); + + OS.ShellShowInFileManager($"{Constants.USER_FOLDER}/export/"); + + }; + favoriteButton.Pressed += () => { Map.Favorite = !Map.Favorite; diff --git a/user/skins/default/ui/buttons/export.png b/user/skins/default/ui/buttons/export.png new file mode 100644 index 0000000000000000000000000000000000000000..4004e8ad74d05657e3b55a416af3d5608a3721e4 GIT binary patch literal 2246 zcmV;%2s!tOP)fUg_-YhzkAL-=iGD8IoBtpL>1rza4&$*0WbhO58!k) z1_Cmm3hjO=Wl~CMODQcWWxtg2ST)9iDtz>VQp!HL7><%2QuM|l=9GOjLqkA zp|Usx;O79|1H5gOvjO}Gz?T6GS8{N^3NxS?z)t{t1c09x=I7_#8-BkZ;c(dfozLeN z#1TLw67k+O0sI=kR{@MwYJh=Cbqrt^fM)>Q;}L)U{CQlzejSeEprxe+2M!!?3BP># zGH%?s;WA~%jvZ)gYvbcV03RdI06YRmIiTog!%Z10s$I;Z(#MkQpd|nZM z9DrWV!HRNrMimC|B!Ew<*>h)|IvxszvOb^hn{{<{FElhXWb5ne5sSsJY11Zb-n$QhgVU#9CuO6u@@?d_m2cOTg8uS7DkabX|W& zO8HYw)8=EbSkUM5fsInYR$pK5@9OHBGYsRo+1c3>*=!aA0|S_vn)3ROD<(Xm9H%wM zfQMBhBV3X1@9ziod}e0mdBZTCJ$m$LmiOxFT>dOVEEaQ#>g?>CmQsG-vaFZ+Zf|d| z+gA}2z7F92wZ?#V1NahvP5i?FU%7GxoJHHVPf97D=<4b!$n$dO?CcztQXaP~>o;UV zUtb@Y=-u9`B%yW9Fu-w~U5?|lQq;N3aarSfZ&}t$Qp#_2cXuaC?X$bPyO*==IL;~d z#Z`n$CBNY~&OXO+=wqynRbYI4{8BodzLrX*+Q!DlTxTW{iM#~h@t&TZ(Utbw)6;Y9 z^y$-&Tb30|rBWZJVQg-0X1mbX*f^+GiRw#0DwXO_CX-L4(`l~d*B!_C8G!HJ4)Gqk zySw`w$9c?goL{l;OeXWUWHR}5DwP^9$Jj+VI_c=>u%@P_Ue4$94@fERGfnf`Jv}{F zQ6?NacI>=qnvb&YTrT&}ow*nI#Rlv^uTK!gS06o6MseD}Qo9#Brz!iJ$VkZ?K>0|4IOb_Bre zatsja!;IG62VlzzK76x*TwDPI?f~$aGP%BU0Dh-JZfA-oQY?A!ivWJ99F1}iPd$_Q ze7@uvaP}`%wx;Mn-(PuG5orTPfdVT!FqwLqh`^8ykxsq4)T-vS-f~Gk|*jXfg5J#L)35 z2RNuw8IVjSU54KdMn@Oi5C&QH?IVdUs8U}8@J|4*c?|f3^5+^wiP3hNchymK9R{}?in5)#;#qA)VW}4?u0N+^RVMM1^HCF zu4~+gREzj>LDMv;Y1$iV3w>^OcGlfY5w>l&=(>KV$mjEibzS!tM`y#~@Lx4e`xiC{ zG)?Obg+hPeZyHv@Fbw`aBn-o7HcivV;3Qih5RmbBygb%#4S_TTgF(}ylagQmcz{2=&@>qk2m}iMHxh!upi3Kl z6T*`OQS4w8J1`p!UhvhUk&sM}FUph_F=3;@qpO&BS%vz5H3xwjhd_-(pvECk;}EEE z2-G+PY8(PJ4uKknK#fD7#vxGS5U6no)Hnjge^x6Fz}g}1#TlSvq=s!tnQYlnOj~h= zDX=sc;zdp>iEK7IJ25dKhlhuK{8npgtK7PE>s+N7;6;RpLVbYaIBrDPjgBnj@+uw^ z%x1G^GMUV9Hk;ka|6^lgZ`rnec1a$utYAElw6PI|D7a-=7B4b5N>L1l!#*Z7D>jma zyyL6sboxQVFqo1v)9LidBS(%fg-n)BJ~JSs!AR z=bk<8fv%t`O|J*=3sqZFl@pe?iOm2$u1=k>O2n;XWx5qoKA>8V%ExI`MIU}I_0Ixsl_6&K`^TOm^m_m=*tY#3AE17y zijIJ?1?%1(u=IXth;<$=ehc8_qC-=OL}I5p)JTyjl$LDYzMU2n>k%||oOPDUQ1=!7 z$m2Jfrm<{p@u@MzgvZno73%*+0#*1$0N>LzZRD26<`Rhn*UF>n@B?cGqe}PJi~bkG zR)oK)>WyB}G;Ma-bAyS6+8R3Mw1&Ht4OmH~Xtluc(}2^-qvG@M<-De8|KsET7wCM! UJ(hhl+W-In07*qoM6N<$f>lyHaR2}S literal 0 HcmV?d00001 diff --git a/user/skins/default/ui/buttons/export.png.import b/user/skins/default/ui/buttons/export.png.import new file mode 100644 index 00000000..33dbb9a9 --- /dev/null +++ b/user/skins/default/ui/buttons/export.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dkpbociv8fgfd" +path="res://.godot/imported/export.png-9d48d4339a04990c70115e465c24c745.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://user/skins/default/ui/buttons/export.png" +dest_files=["res://.godot/imported/export.png-9d48d4339a04990c70115e465c24c745.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 From 417556e8292b92e810b5f84495a8efd58ea7dcc6 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Mon, 22 Jun 2026 19:54:01 -0400 Subject: [PATCH 02/23] redundant --- prefabs/map_info_container.tscn | 1 + 1 file changed, 1 insertion(+) diff --git a/prefabs/map_info_container.tscn b/prefabs/map_info_container.tscn index b6d30a81..7dc3c47d 100644 --- a/prefabs/map_info_container.tscn +++ b/prefabs/map_info_container.tscn @@ -403,6 +403,7 @@ filters = PackedStringArray("*.mp4") use_native_dialog = true [node name="Copy" type="Button" parent="Info/ScrollContainer/HBoxContainer/Subholder/Buttons" unique_id=2053076461] +visible = false layout_mode = 2 tooltip_text = "Copy" focus_mode = 0 From 83beff5f42758b28705021beddeff4ed36d28c10 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Mon, 22 Jun 2026 19:54:09 -0400 Subject: [PATCH 03/23] dddssdfdffdffdffdffdfdf --- scripts/map/MapParser.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/scripts/map/MapParser.cs b/scripts/map/MapParser.cs index 2459ac7d..fdb42377 100644 --- a/scripts/map/MapParser.cs +++ b/scripts/map/MapParser.cs @@ -74,13 +74,6 @@ public static void ExportEncode(Map map) if (!Directory.Exists(exportPath)) Directory.CreateDirectory(exportPath); - /* - uint32; ms - 1 byte; quantum - 1 byte OR int32; x - 1 byte OR int32; y - */ - using var ms = new MemoryStream(); using (var archive = new ZipArchive(ms, ZipArchiveMode.Create)) { From 6a82546be83dc3b32290f48f3405003d5c2e8209 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Mon, 22 Jun 2026 21:05:14 -0400 Subject: [PATCH 04/23] bye collection --- scripts/map/MapCache.cs | 6 +++--- scripts/map/MapParser.cs | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/scripts/map/MapCache.cs b/scripts/map/MapCache.cs index ac1d6929..ccac8681 100644 --- a/scripts/map/MapCache.cs +++ b/scripts/map/MapCache.cs @@ -164,7 +164,7 @@ private static void addNonCachedFiles(string[] files) { var map = MapParser.Decode(file); map.Collection = file.GetBaseDir().Split("/")[^1]; - map.FilePath = $"{Constants.USER_FOLDER}/maps/{map.Collection}/{map.Name}.{Constants.DEFAULT_MAP_EXT}"; + map.FilePath = $"{Constants.USER_FOLDER}/maps/{map.Name}.{Constants.DEFAULT_MAP_EXT}"; map.Hash = GetMd5Checksum(file); File.Move(file, map.FilePath); InsertMap(map); @@ -206,8 +206,8 @@ public static int InsertMap(Map map) return -1; } - string newPath = Path.Combine(MapUtil.MapsFolder, map.Collection, map.Name); - string existingPath = Path.Combine(MapUtil.MapsFolder, map.Collection, existing?.FilePath ?? updated.FilePath); + string newPath = Path.Combine(MapUtil.MapsFolder, map.Name); + string existingPath = Path.Combine(MapUtil.MapsFolder, existing?.FilePath ?? updated.FilePath); if (existingPath != newPath) { diff --git a/scripts/map/MapParser.cs b/scripts/map/MapParser.cs index fdb42377..7d2c1bff 100644 --- a/scripts/map/MapParser.cs +++ b/scripts/map/MapParser.cs @@ -135,9 +135,7 @@ public static void Encode(Map map, bool logBenchmark = false) { double start = Time.GetTicksUsec(); - map.Collection = $"default"; - - string mapDirectory = $"{Constants.USER_FOLDER}/maps/{map.Collection}"; + string mapDirectory = $"{Constants.USER_FOLDER}/maps"; string mapFilePath = Path.Combine(mapDirectory, $"{map.Name}.{Constants.DEFAULT_MAP_EXT}"); if (!Directory.Exists(mapDirectory)) Directory.CreateDirectory(mapDirectory); From fa3c268de46f5fbbdc5329f092085bef63b0c6d9 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Mon, 22 Jun 2026 21:05:51 -0400 Subject: [PATCH 05/23] selects file now --- scripts/ui/menu/play/MapInfoContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/ui/menu/play/MapInfoContainer.cs b/scripts/ui/menu/play/MapInfoContainer.cs index 364a2afb..e146a2b6 100644 --- a/scripts/ui/menu/play/MapInfoContainer.cs +++ b/scripts/ui/menu/play/MapInfoContainer.cs @@ -134,9 +134,9 @@ public override void _Ready() _ = ToastNotification.Notify($"Exporting to {exportFilePath}", 1); MapParser.ExportEncode(Map); - _ = ToastNotification.Notify($"Done! Opening export folder...", 0); + _ = ToastNotification.Notify($"Done! Opening export...", 0); - OS.ShellShowInFileManager($"{Constants.USER_FOLDER}/export/"); + OS.ShellShowInFileManager(exportFilePath); }; From 37b4c3e4783e5013fa51ae0a354a6bbdd5977261 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Tue, 23 Jun 2026 14:08:43 -0400 Subject: [PATCH 06/23] easy --- scripts/util/Misc.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/util/Misc.cs b/scripts/util/Misc.cs index 38a1716c..19368c09 100644 --- a/scripts/util/Misc.cs +++ b/scripts/util/Misc.cs @@ -1,4 +1,8 @@ +using System; using System.Globalization; +using System.IO; +using System.Security.Cryptography; +using System.Text; using Godot; namespace Util; @@ -61,6 +65,24 @@ public static void CopyProperties(Node node, Node reference) } } + public static byte[] HashFiles(string[] paths) + { + using var md5 = MD5.Create(); + + foreach (var path in paths) // we do not need to order the paths since it will always be the same -fog + { + byte[] filePathBytes = Encoding.UTF8.GetBytes(path); + byte[] fileData = File.ReadAllBytes(path); + + md5.TransformBlock(filePathBytes, 0, filePathBytes.Length, null, 0); + md5.TransformBlock(fileData, 0, fileData.Length, null, 0); + } + + md5.TransformFinalBlock(Array.Empty(), 0 ,0); + + return md5.Hash; + } + public static void CopyReference(Node node, Node reference) { CopyProperties(node, reference); From 0fada8188d8d8430559a3af76ae8431c61ab5daa Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Tue, 23 Jun 2026 17:29:32 -0400 Subject: [PATCH 07/23] useless --- scripts/util/Misc.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/util/Misc.cs b/scripts/util/Misc.cs index 19368c09..510bfa2c 100644 --- a/scripts/util/Misc.cs +++ b/scripts/util/Misc.cs @@ -71,10 +71,7 @@ public static byte[] HashFiles(string[] paths) foreach (var path in paths) // we do not need to order the paths since it will always be the same -fog { - byte[] filePathBytes = Encoding.UTF8.GetBytes(path); byte[] fileData = File.ReadAllBytes(path); - - md5.TransformBlock(filePathBytes, 0, filePathBytes.Length, null, 0); md5.TransformBlock(fileData, 0, fileData.Length, null, 0); } From ce211679f2962649d0627aff0697385e5d4c5d78 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Tue, 23 Jun 2026 17:29:41 -0400 Subject: [PATCH 08/23] deprecated --- scripts/ui/menu/play/MapInfoContainer.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/ui/menu/play/MapInfoContainer.cs b/scripts/ui/menu/play/MapInfoContainer.cs index e146a2b6..2e11feae 100644 --- a/scripts/ui/menu/play/MapInfoContainer.cs +++ b/scripts/ui/menu/play/MapInfoContainer.cs @@ -161,17 +161,17 @@ public override void _Ready() // MapManager.InsertVideo(Map, file); //}; - copyButton.Pressed += () => - { - copyDialog.Popup(); + // copyButton.Pressed += () => + // { + // copyDialog.Popup(); - }; + // }; - copyDialog.FileSelected += (path) => - { - File.Copy(Map.FilePath, path); - _ = ToastNotification.Notify($"Copied to {path}"); - }; + // copyDialog.FileSelected += (path) => + // { + // File.Copy(Map.FolderPath, path); + // _ = ToastNotification.Notify($"Copied to {path}"); + // }; deleteButton.Pressed += () => { From 068693c43ba7a7085742d3dfb72cccc4362f1aa5 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Tue, 23 Jun 2026 17:30:28 -0400 Subject: [PATCH 09/23] adjust to map.cs change --- scripts/SoundManager.cs | 4 ++-- scripts/game/managers/ReplayManager.cs | 12 ++++++++---- scripts/game/ui/PlaytestOverlay.cs | 2 +- scripts/map/Map.cs | 17 +++++++++++------ scripts/map/Replay.cs | 2 +- scripts/scenes/Game.cs | 4 ++-- scripts/scenes/Results.cs | 2 +- 7 files changed, 26 insertions(+), 17 deletions(-) diff --git a/scripts/SoundManager.cs b/scripts/SoundManager.cs index 9eb59133..f0ecf4eb 100644 --- a/scripts/SoundManager.cs +++ b/scripts/SoundManager.cs @@ -221,7 +221,7 @@ public static void PlayJukebox(Map map, bool setRichPresence = true) JukeboxIndex = MapManager.Maps.FindIndex(x => x.Id == map.Id); - Song.Stream = Util.Audio.LoadFromFile($"{MapUtil.MapsCacheFolder}/{map.Name}/audio.{map.AudioExt}"); + Song.Stream = Util.Audio.LoadFromFile($"{MapUtil.MapsFolder}/{map.Name}/audio.{map.AudioExt}"); Song.Play(); Instance.JukeboxPlayed?.Invoke(map); @@ -280,7 +280,7 @@ public static void StartMapSelectionPlayback(Map map, bool setRichPresence = tru } } - Song.Stream = Util.Audio.LoadFromFile($"{MapUtil.MapsCacheFolder}/{map.Name}/audio.{map.AudioExt}"); + Song.Stream = Util.Audio.LoadFromFile($"{MapUtil.MapsFolder}/{map.Name}/audio.{map.AudioExt}"); Song.Play(0); Instance.JukeboxPlayed?.Invoke(map); diff --git a/scripts/game/managers/ReplayManager.cs b/scripts/game/managers/ReplayManager.cs index 42166b59..631e5332 100644 --- a/scripts/game/managers/ReplayManager.cs +++ b/scripts/game/managers/ReplayManager.cs @@ -1,4 +1,7 @@ using System; +using System.IO; + +// using System.IO; using System.Linq; using System.Security.Cryptography; using Godot; @@ -28,7 +31,7 @@ public enum Mode public string ReplayPath; public Vector2 CursorPosition { get; private set; } - private FileAccess file; + private Godot.FileAccess file; private ulong statusOffset, frameCountOffset; public void NewReplay(Attempt attempt) @@ -39,7 +42,7 @@ public void NewReplay(Attempt attempt) ReplayPath = $"{Constants.USER_FOLDER}/replays/{attempt.ID}.phxr"; - file = FileAccess.Open(ReplayPath, FileAccess.ModeFlags.Write); + file = Godot.FileAccess.Open(ReplayPath, Godot.FileAccess.ModeFlags.Write); file.StoreString("phxr"); // sig file.Store8(1); // replay file version @@ -69,7 +72,8 @@ public void NewReplay(Attempt attempt) } string serializedMods = string.Join("_", mods); - string mapName = attempt.Map.FilePath.GetFile().GetBaseName(); + // string mapName = attempt.Map.FilePath.GetFile().GetBaseName(); + string mapName = Path.GetDirectoryName(attempt.Map.FolderPath); string player = "You"; void storeSizedString(string data) @@ -126,7 +130,7 @@ public void SaveReplay(Attempt attempt) file.Close(); // open replay to store hash - file = FileAccess.Open($"{Constants.USER_FOLDER}/replays/{attempt.ID}.phxr", FileAccess.ModeFlags.ReadWrite); + file = Godot.FileAccess.Open($"{Constants.USER_FOLDER}/replays/{attempt.ID}.phxr", Godot.FileAccess.ModeFlags.ReadWrite); ulong length = file.GetLength(); byte[] hash = SHA256.HashData(file.GetBuffer((long)length)); file.StoreBuffer(hash); diff --git a/scripts/game/ui/PlaytestOverlay.cs b/scripts/game/ui/PlaytestOverlay.cs index b6917758..1b6102dc 100644 --- a/scripts/game/ui/PlaytestOverlay.cs +++ b/scripts/game/ui/PlaytestOverlay.cs @@ -74,7 +74,7 @@ public void UpdatePlaytestOverlay(bool show) speedValue = speedDouble; } - var map = MapParser.Decode(oldAttempt.Map.FilePath, Rhythia.AudioFilePath); + var map = MapParser.Decode(oldAttempt.Map.FolderPath, Rhythia.AudioFilePath); Game.Attempt = new(map, speedValue, GetStartFrom(startFromEdit) * 1000, Rhythia.TempCam, Rhythia.TempMods); SceneManager.ReloadCurrentScene(); diff --git a/scripts/map/Map.cs b/scripts/map/Map.cs index 15c8c76f..118b97a0 100644 --- a/scripts/map/Map.cs +++ b/scripts/map/Map.cs @@ -17,15 +17,20 @@ public partial class Map : RefCounted public int Id { get; set; } public string Name { get; set; } = string.Empty; + public DateTime LastModifiedMetadata { get; set; } + public DateTime LastModifiedNotes { get; set; } - public string Hash { get; set; } + /// + /// The hash of the metadata.json, then the objects.phxmo in order + /// + public string MetadataObjectHash { get; set; } public string Collection { get; set; } = string.Empty; [Ignore] public MapSet MapSet { get; set; } - public string FilePath { get; set; } = string.Empty; + public string FolderPath { get; set; } = string.Empty; public bool Favorite { get; set; } @@ -86,7 +91,7 @@ public Note[] TryParseNotes() { try { - notes = MapParser.DecodePHXMO($"{MapUtil.MapsCacheFolder}/{Name}/objects.phxmo"); + notes = MapParser.DecodePHXMO($"{MapUtil.MapsFolder}/{Name}/objects.phxmo"); return notes; } catch @@ -97,7 +102,7 @@ public Note[] TryParseNotes() private Texture2D getCover() { - string path = $"{MapUtil.MapsCacheFolder}/{Name}"; + string path = $"{MapUtil.MapsFolder}/{Name}"; if (cover == DefaultCover && File.Exists($"{path}/cover.png")) { @@ -115,9 +120,9 @@ private Texture2D getCover() public Map() { } - public Map(string filePath, Note[] data = null, string id = null, string artist = "", string title = "", float rating = 0, string[] mappers = null, int difficulty = 0, string difficultyName = null, int? length = null, byte[] audioBuffer = null, byte[] coverBuffer = null, byte[] videoBuffer = null, bool ephemeral = false, string artistLink = "", string artistPlatform = "") + public Map(string folderPath, Note[] data = null, string id = null, string artist = "", string title = "", float rating = 0, string[] mappers = null, int difficulty = 0, string difficultyName = null, int? length = null, byte[] audioBuffer = null, byte[] coverBuffer = null, byte[] videoBuffer = null, bool ephemeral = false, string artistLink = "", string artistPlatform = "") { - FilePath = filePath; + FolderPath = folderPath; Ephemeral = ephemeral; Artist = (artist ?? "").StripEscapes(); ArtistLink = artistLink; diff --git a/scripts/map/Replay.cs b/scripts/map/Replay.cs index 6da741ea..a2764ed6 100644 --- a/scripts/map/Replay.cs +++ b/scripts/map/Replay.cs @@ -168,7 +168,7 @@ public Replay(string path) MapID = FileBuffer.GetString((int)FileBuffer.GetUInt32()); MapNoteCount = FileBuffer.GetUInt64(); - MapFilePath = $"{Constants.USER_FOLDER}/maps/default/{MapID}.phxm"; + MapFilePath = $"{Constants.USER_FOLDER}/maps/{MapID}.phxm"; if (!File.Exists(MapFilePath)) { diff --git a/scripts/scenes/Game.cs b/scripts/scenes/Game.cs index 5858faaa..a507e2e6 100644 --- a/scripts/scenes/Game.cs +++ b/scripts/scenes/Game.cs @@ -170,7 +170,7 @@ public static void Play(Map map, double speed, double startFrom, CameraMode came StartQueued = true; - var parsedMap = MapParser.Decode(map.FilePath, Rhythia.AudioFilePath); + var parsedMap = MapParser.Decode(map.FolderPath, Rhythia.AudioFilePath); Attempt = new(parsedMap, speed, startFrom, cameraMode, mods, players, replays); if (!Attempt.IsReplay) @@ -189,7 +189,7 @@ public void Restart() Runner.Stop(false); var oldAttempt = Attempt; - var map = MapParser.Decode(oldAttempt.Map.FilePath, Rhythia.AudioFilePath); + var map = MapParser.Decode(oldAttempt.Map.FolderPath, Rhythia.AudioFilePath); Attempt = new(map, oldAttempt.Speed, oldAttempt.StartFrom, oldAttempt.CameraMode, oldAttempt.Modifiers, oldAttempt.Players, oldAttempt.Replays); SceneManager.ReloadCurrentScene(); diff --git a/scripts/scenes/Results.cs b/scripts/scenes/Results.cs index e775065f..916e4664 100644 --- a/scripts/scenes/Results.cs +++ b/scripts/scenes/Results.cs @@ -173,7 +173,7 @@ public void Replay() { var attempt = Game.Attempt; - Map map = MapParser.Decode(attempt.Map.FilePath); + Map map = MapParser.Decode(attempt.Map.FolderPath); map.Ephemeral = attempt.Map.Ephemeral; SoundManager.Song.Stop(); From 9de2b082cbb4e60b201364272c5af175d11cf615 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Tue, 23 Jun 2026 17:30:51 -0400 Subject: [PATCH 10/23] map folder cache --- scripts/map/MapCache.cs | 257 +++++++++++++++++++++++------------- scripts/map/MapManager.cs | 18 +-- scripts/map/MapParser.cs | 268 +++++++++++++++++++++++++------------- 3 files changed, 354 insertions(+), 189 deletions(-) diff --git a/scripts/map/MapCache.cs b/scripts/map/MapCache.cs index ccac8681..7f4e5df8 100644 --- a/scripts/map/MapCache.cs +++ b/scripts/map/MapCache.cs @@ -1,11 +1,13 @@ -using System; +using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; using System.IO; using System.IO.Compression; using System.Linq; using System.Security.Cryptography; using System.Threading.Tasks; using Godot; +using Octokit; using Util; public static class MapCache @@ -28,12 +30,24 @@ public static void Load(bool fullSync) try { - string[] files = Directory.GetFiles(MapUtil.MapsFolder, $"*.{Constants.DEFAULT_MAP_EXT}", SearchOption.AllDirectories); + // string[] files = Directory.GetFiles(MapUtil.MapsFolder, $"*.{Constants.DEFAULT_MAP_EXT}", SearchOption.AllDirectories); + + // List mapsList = Directory + // .GetFiles(MapUtil.MapsFolder, $"*.{Constants.DEFAULT_MAP_EXT}", SearchOption.AllDirectories) + // .Concat(Directory.GetDirectories(MapUtil.MapsFolder, "*", SearchOption.AllDirectories)) + // .ToList(); + + // Map files go first since they will be encoded to folders after they get parsed in MapParser.cs + List mapsList = Directory.GetDirectories(MapUtil.MapsFolder, "*", SearchOption.AllDirectories) + .Concat(Directory.GetFiles(MapUtil.MapsFolder,$"*.{Constants.DEFAULT_MAP_EXT}", SearchOption.AllDirectories)) + .ToList(); + + string[] toParseMaps = mapsList.ToArray(); if (fullSync) { - syncFiles(files); - addNonCachedFiles(files); + syncFiles(toParseMaps); + addNonCachedFiles(toParseMaps); OnFilesSyncFinished?.Invoke(FilesSynced.Value); FilesToSync.Value = 0; @@ -48,35 +62,39 @@ public static void Load(bool fullSync) } } - private static void syncFiles(string[] files) + private static void syncFiles(string[] toParseMaps) { var maps = FetchAll(); FilesToSync.Value = maps.Count; FilesSynced.Value = 0; - for (int i = 0; i < files.Length; i++) + for (int i = 0; i < toParseMaps.Length; i++) { - files[i] = BackSlashToForwardSlash(files[i]); + toParseMaps[i] = BackSlashToForwardSlash(toParseMaps[i]); } - var filesHashSet = files.ToHashSet(); + var mapsHashSet = toParseMaps.ToHashSet(); foreach (var map in maps) { - string filePath = BackSlashToForwardSlash(map.FilePath); + string mapPath = BackSlashToForwardSlash(map.FolderPath); - if (filesHashSet.Contains(filePath)) + // Checks if the map is actually inside the maps folder + if (mapsHashSet.Contains(mapPath)) { - string checksum = GetMd5Checksum(filePath); + string checksum = GetMd5Checksum(mapPath); + DateTime metadataModifiedDate = File.GetLastWriteTime(Path.Combine(mapPath, "metadata.json")); + DateTime objectModifiedDate = File.GetLastWriteTime(Path.Combine(mapPath, "objects.phxmo")); - if (map.Hash == checksum) - { - if (!Directory.Exists($"{MapUtil.MapsCacheFolder}/{map.Name}")) - { - InsertIntoMapCacheFolder(map); - } + GD.Print($"{Path.Combine(mapPath, "metadata.json")} = {metadataModifiedDate}"); + bool metadataCheck = metadataModifiedDate == map.LastModifiedMetadata; + bool objectsCheck = objectModifiedDate == map.LastModifiedNotes; + + if (map.MetadataObjectHash == checksum || metadataCheck || objectsCheck) + { + GD.Print("skip"); FilesSynced.Value += 1; continue; } @@ -85,75 +103,124 @@ private static void syncFiles(string[] files) try { - newMap = MapParser.Decode(filePath, null, false, true); + newMap = MapParser.Decode(mapPath, null, false, true); } catch (Exception ex) { Logger.Error(ex); - File.Delete(filePath); + if (File.Exists(mapPath)) + { + File.Delete(mapPath); + } + else if (Directory.Exists(mapPath)) + { + Directory.Delete(mapPath, true); + } DatabaseService.Connection.Delete(map); FilesSynced.Value += 1; continue; } + newMap.LastModifiedMetadata = metadataModifiedDate; + newMap.LastModifiedNotes = objectModifiedDate; + newMap.Id = map.Id; - newMap.Hash = checksum; + newMap.MetadataObjectHash = checksum; DatabaseService.Connection.Update(newMap); - InsertIntoMapCacheFolder(map); + // InsertIntoMapCacheFolder(map); Logger.Log($"Updated cached map: {newMap.Name}"); - FilesSynced.Value += 1; continue; } else { - removeCacheFolder(map); + // removeCacheFolder(map); + try + { + Directory.Delete($"{MapUtil.MapsFolder}/{map.Name}", true); + } + catch + { + return; + } DatabaseService.Connection.Delete(map); - Logger.Log($"Removed {filePath} from the cache, as it no longer exists."); + Logger.Log($"Removed {mapPath} from the cache, as it no longer exists."); FilesSynced.Value += 1; } } } - public static void InsertIntoMapCacheFolder(Map map) - { - string path = $"{MapUtil.MapsCacheFolder}/{map.Name}"; - using var stream = File.OpenRead(map.FilePath); - var archive = new ZipArchive(stream); - - if (Directory.Exists(path)) - { - Directory.Delete(path, true); - } - - archive.ExtractToDirectory(path, true); - } - - private static void removeCacheFolder(Map map) - { - try - { - Directory.Delete($"{MapUtil.MapsCacheFolder}/{map.Name}", true); - } - catch - { - return; - } - } - - private static void addNonCachedFiles(string[] files) + // public static void InsertIntoMapCacheFolder(Map map) + // { + // string path = $"{MapUtil.MapsCacheFolder}/{map.Name}"; + + // // for phxm shit i guess + // if (File.Exists(map.FolderPath)) + // { + // using var stream = File.OpenRead(map.FolderPath); + // var archive = new ZipArchive(stream); + + // if (Directory.Exists(path)) + // { + // Directory.Delete(path, true); + // } + + // archive.ExtractToDirectory(path, true); + // } + // else if (Directory.Exists(map.FolderPath)) + // { + // GD.Print("PATH PATH PATH!!!"); + // if (Directory.Exists(path)) + // { + // Directory.Delete(path, true); + // } + + // Directory.CreateDirectory(path); + + // foreach (string file in Directory.GetFiles(map.FolderPath)) + // { + // string destFile = Path.Combine(path, Path.GetFileName(file)); + // File.Copy(file, destFile, overwrite: true); + // } + // } + + // // using var stream = File.OpenRead(map.FilePath); + // // var archive = new ZipArchive(stream); + + // // if (Directory.Exists(path)) + // // { + // // Directory.Delete(path, true); + // // } + + // // archive.ExtractToDirectory(path, true); + + // } + + // private static void removeCacheFolder(Map map) + // { + // try + // { + // Directory.Delete($"{MapUtil.MapsCacheFolder}/{map.Name}", true); + // } + // catch + // { + // return; + // } + // } + + private static void addNonCachedFiles(string[] toParseMaps) { var maps = FetchAll(); HashSet hashSet = new(); - maps.ForEach(map => hashSet.Add(map.FilePath)); + maps.ForEach(map => hashSet.Add(map.FolderPath)); - foreach (string file in files) + foreach (string toParseMap in toParseMaps) { - if (hashSet.Contains(BackSlashToForwardSlash(file))) + if (hashSet.Contains(BackSlashToForwardSlash(toParseMap))) { continue; } @@ -162,16 +229,16 @@ private static void addNonCachedFiles(string[] files) try { - var map = MapParser.Decode(file); - map.Collection = file.GetBaseDir().Split("/")[^1]; - map.FilePath = $"{Constants.USER_FOLDER}/maps/{map.Name}.{Constants.DEFAULT_MAP_EXT}"; - map.Hash = GetMd5Checksum(file); - File.Move(file, map.FilePath); + var map = MapParser.Decode(toParseMap); + // var map = !Directory.Exists(file) ? MapParser.Decode(file) : MapParser.DecodeFolder(file); + map.FolderPath = $"{Constants.USER_FOLDER}/maps/{map.Name}"; + // map.FilePath = !Directory.Exists(map.FilePath) ? $"{Constants.USER_FOLDER}/maps/{map.Name}.{Constants.DEFAULT_MAP_EXT}" : $"{Constants.USER_FOLDER}/maps/{map.Name}"; + map.MetadataObjectHash = GetMd5Checksum(toParseMap); InsertMap(map); } catch { - File.Delete(file); + Directory.Delete(toParseMap, true); Logger.Log($"Failed to add map non-cached map"); } @@ -181,7 +248,7 @@ private static void addNonCachedFiles(string[] files) public static int InsertMap(Map map) { - var existing = DatabaseService.Connection.Find(x => x.Hash == x.Hash); + var existing = DatabaseService.Connection.Find(x => x.MetadataObjectHash == map.MetadataObjectHash); var updated = DatabaseService.Connection.Find(x => x.Name == map.Name); try @@ -194,9 +261,8 @@ public static int InsertMap(Map map) } DatabaseService.Connection.Insert(map); - InsertIntoMapCacheFolder(map); - return DatabaseService.Connection.Get(x => x.Hash == map.Hash).Id; + return DatabaseService.Connection.Get(x => x.MetadataObjectHash == map.MetadataObjectHash).Id; } catch (Exception e) { @@ -207,11 +273,11 @@ public static int InsertMap(Map map) } string newPath = Path.Combine(MapUtil.MapsFolder, map.Name); - string existingPath = Path.Combine(MapUtil.MapsFolder, existing?.FilePath ?? updated.FilePath); + string existingPath = Path.Combine(MapUtil.MapsFolder, existing?.FolderPath ?? updated.FolderPath); if (existingPath != newPath) { - File.Delete(newPath); + Directory.Delete(newPath, true); return -1; } @@ -224,7 +290,6 @@ public static void UpdateMap(Map map) try { DatabaseService.Connection.Update(map); - InsertIntoMapCacheFolder(map); } catch (Exception e) { @@ -253,7 +318,7 @@ public static void OrderAndSetMaps() { foreach (var map in maps) { - string path = $"{MapUtil.MapsCacheFolder}/{map.Name}"; + string path = $"{MapUtil.MapsFolder}/{map.Name}"; if (map.Cover == Map.DefaultCover && File.Exists($"{path}/cover.png")) { @@ -298,39 +363,45 @@ public static void OrderAndSetMaps() MapManager.Maps = sortedMaps; } - public static List ConvertToMapSets(IEnumerable maps) - { - var groupedMaps = maps - .GroupBy(u => u.Collection) - .Select(x => x.ToList()) - .ToList(); + // public static List ConvertToMapSets(IEnumerable maps) + // { + // var groupedMaps = maps + // .GroupBy(u => u.Collection) + // .Select(x => x.ToList()) + // .ToList(); - var mapSets = new List(); + // var mapSets = new List(); - foreach (var mapSet in groupedMaps) - { - var set = new MapSet() - { - Directory = mapSet.First().Collection, - Maps = mapSet - }; + // foreach (var mapSet in groupedMaps) + // { + // var set = new MapSet() + // { + // Directory = mapSet.First().Collection, + // Maps = mapSet + // }; - set.Maps.ForEach(x => x.MapSet = set); - mapSets.Add(set); - } + // set.Maps.ForEach(x => x.MapSet = set); + // mapSets.Add(set); + // } - return mapSets; - } + // return mapSets; + // } public static string GetMd5Checksum(string path) { - using (var md5 = MD5.Create()) - { - using (var stream = File.OpenRead(path)) - { - return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", string.Empty).ToLower(); - } - } + string metadataPath = Path.Combine(path, "metadata.json"); + string objectsPath = Path.Combine(path, "objects.phxmo"); + byte[] hash = Misc.HashFiles([metadataPath, objectsPath]); + + return BitConverter.ToString(hash).Replace("-", string.Empty).ToLower(); + + // using (var md5 = MD5.Create()) + // { + // using (var stream = File.OpenRead(path)) + // { + // return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", string.Empty).ToLower(); + // } + // } } public static List FetchAll() => DatabaseService.Connection.Table().ToList(); diff --git a/scripts/map/MapManager.cs b/scripts/map/MapManager.cs index df690414..6d5c0d5e 100644 --- a/scripts/map/MapManager.cs +++ b/scripts/map/MapManager.cs @@ -58,35 +58,35 @@ public static void InsertVideo(Map map, string path) map.VideoBuffer = videoBuffer; - var oldmap = MapParser.Decode(map.FilePath); + var oldmap = MapParser.Decode(map.FolderPath); map.Mappers = map.CachedMappers.Split("_"); map.AudioBuffer = oldmap.AudioBuffer; map.CoverBuffer = oldmap.CoverBuffer; - File.Delete(map.FilePath); + Directory.Delete(map.FolderPath); MapParser.Encode(map); - map.Hash = MapCache.GetMd5Checksum(map.FilePath); + map.FolderPath = MapCache.GetMd5Checksum(map.FolderPath); Update(map); } public static void RemoveVideo(Map map) { - _ = Godot.FileAccess.Open(map.FilePath, Godot.FileAccess.ModeFlags.Read); + _ = Godot.FileAccess.Open(map.FolderPath, Godot.FileAccess.ModeFlags.Read); map.VideoBuffer = null; - var oldmap = MapParser.Decode(map.FilePath); + var oldmap = MapParser.Decode(map.FolderPath); map.Mappers = map.PrettyMappers.Split(" "); map.AudioBuffer = oldmap.AudioBuffer; map.CoverBuffer = oldmap.CoverBuffer; - File.Delete(map.FilePath); + File.Delete(map.FolderPath); MapParser.Encode(map); - map.Hash = MapCache.GetMd5Checksum(map.FilePath); + map.MetadataObjectHash = MapCache.GetMd5Checksum(map.FolderPath); Update(map); } @@ -96,11 +96,11 @@ public static void Delete(Map map) { try { - File.Delete(map.FilePath); + File.Delete(map.FolderPath); } catch { - if (File.Exists(map.FilePath)) + if (File.Exists(map.FolderPath)) { Logger.Error("Unable to delete map"); return; diff --git a/scripts/map/MapParser.cs b/scripts/map/MapParser.cs index 7d2c1bff..572ef7b9 100644 --- a/scripts/map/MapParser.cs +++ b/scripts/map/MapParser.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Godot; using Godot.Collections; +using Util; public partial class MapParser : Node { @@ -27,7 +28,7 @@ public static async Task BulkImport(string[] files, bool notify = false) { if (files.Length == 0 || files == null) return; - if (notify) ToastNotification.Notify($"Importing {files.Length} map(s)"); + if (notify) _ = ToastNotification.Notify($"Importing {files.Length} map(s)"); await Task.Run(() => { @@ -64,7 +65,7 @@ await Task.Run(() => }); SoundManager.UpdateJukeboxQueue(); - if (notify) ToastNotification.Notify($"Finished importing {files.Length} map(s)"); + if (notify) _ = ToastNotification.Notify($"Finished importing {files.Length} map(s)"); } public static void ExportEncode(Map map) @@ -127,7 +128,6 @@ void addAsset(string name, byte[] buffer) if (map.VideoBuffer != null) addAsset($"video.mp4", map.VideoBuffer); } - map.Hash = Convert.ToHexString(MD5.HashData(ms.ToArray())).ToLower(); File.WriteAllBytes(exportFilePath, ms.ToArray()); } @@ -136,9 +136,11 @@ public static void Encode(Map map, bool logBenchmark = false) double start = Time.GetTicksUsec(); string mapDirectory = $"{Constants.USER_FOLDER}/maps"; - string mapFilePath = Path.Combine(mapDirectory, $"{map.Name}.{Constants.DEFAULT_MAP_EXT}"); + string mapFolderPath = Path.Combine(mapDirectory, $"{map.Name}"); + // string mapFilePath = Path.Combine(mapDirectory, $"{map.Name}.{Constants.DEFAULT_MAP_EXT}"); if (!Directory.Exists(mapDirectory)) Directory.CreateDirectory(mapDirectory); + if (!Directory.Exists(mapFolderPath)) Directory.CreateDirectory(mapFolderPath); /* uint32; ms @@ -147,63 +149,65 @@ public static void Encode(Map map, bool logBenchmark = false) 1 byte OR int32; y */ - using var ms = new MemoryStream(); - using (var archive = new ZipArchive(ms, ZipArchiveMode.Create)) + File.WriteAllText(Path.Combine(mapFolderPath, "metadata.json"), map.EncodeMeta()); + + using var stream = File.Create(Path.Combine(mapFolderPath, "objects.phxmo")); + using BinaryWriter bw = new BinaryWriter(stream); + + bw.Write((uint)12); + bw.Write((uint)map.Notes.Length); + foreach (var note in map.Notes) { - var metadata = archive.CreateEntry("metadata.json", CompressionLevel.NoCompression); - using (var writer = new StreamWriter(metadata.Open())) - writer.Write(map.EncodeMeta()); - var objects = archive.CreateEntry("objects.phxmo", CompressionLevel.NoCompression); - using (var objs = objects.Open()) + bool quantum = (int)note.X != note.X || (int)note.Y != note.Y || note.X < -1 || note.X > 1 || note.Y < -1 || note.Y > 1; + bw.Write((uint)note.Millisecond); + bw.Write(Convert.ToByte(quantum)); + if (quantum) { - using BinaryWriter bw = new BinaryWriter(objs); - bw.Write((uint)12); - bw.Write((uint)map.Notes.Length); - foreach (var note in map.Notes) - { - bool quantum = (int)note.X != note.X || (int)note.Y != note.Y || note.X < -1 || note.X > 1 || note.Y < -1 || note.Y > 1; - bw.Write((uint)note.Millisecond); - bw.Write(Convert.ToByte(quantum)); - if (quantum) - { - bw.Write((float)note.X); - bw.Write((float)note.Y); - } - else - { - bw.Write((byte)(note.X + 1)); - bw.Write((byte)(note.Y + 1)); - } - } - bw.Write(0); // timing point count - bw.Write(0); // brightness count - bw.Write(0); // contrast count - bw.Write(0); // saturation count - bw.Write(0); // blur count - bw.Write(0); // fov count - bw.Write(0); // tint count - bw.Write(0); // position count - bw.Write(0); // rotation count - bw.Write(0); // ar factor count - bw.Write(0); // text count + bw.Write((float)note.X); + bw.Write((float)note.Y); } - - void addAsset(string name, byte[] buffer) + else { - var asset = archive.CreateEntry(name, CompressionLevel.NoCompression); - using var stream = asset.Open(); - stream.Write(buffer, 0, buffer.Length); + bw.Write((byte)(note.X + 1)); + bw.Write((byte)(note.Y + 1)); } + } - if (map.AudioBuffer != null) addAsset($"audio.{map.AudioExt}", map.AudioBuffer); - if (map.CoverBuffer != null) addAsset($"cover.png", map.CoverBuffer); - if (map.VideoBuffer != null) addAsset($"video.mp4", map.VideoBuffer); + bw.Write(0); // timing point count + bw.Write(0); // brightness count + bw.Write(0); // contrast count + bw.Write(0); // saturation count + bw.Write(0); // blur count + bw.Write(0); // fov count + bw.Write(0); // tint count + bw.Write(0); // position count + bw.Write(0); // rotation count + bw.Write(0); // ar factor count + bw.Write(0); // text count + + void addAsset(string name, byte[] buffer) + { + // var asset = archive.CreateEntry(name, CompressionLevel.NoCompression); + // using var stream = asset.Open(); + // stream.Write(buffer, 0, buffer.Length); + + string assetPath = Path.Combine(mapFolderPath, name); + File.WriteAllBytes(assetPath, buffer); } - map.Hash = Convert.ToHexString(MD5.HashData(ms.ToArray())).ToLower(); - File.WriteAllBytes(mapFilePath, ms.ToArray()); - map.FilePath = mapFilePath; - MapCache.InsertMap(map); + if (map.AudioBuffer != null) addAsset($"audio.{map.AudioExt}", map.AudioBuffer); + if (map.CoverBuffer != null) addAsset($"cover.png", map.CoverBuffer); + if (map.VideoBuffer != null) addAsset($"video.mp4", map.VideoBuffer); + + byte[] hash = Misc.HashFiles([Path.Combine(mapFolderPath, "metadata.json"), Path.Combine(mapFolderPath, "objects.phxmo")]); + + map.MetadataObjectHash = BitConverter.ToString(hash).Replace("-", "").ToLower(); + + map.LastModifiedMetadata = File.GetLastWriteTime(Path.Combine(mapFolderPath, "metadata.json")); + map.LastModifiedNotes = File.GetLastWriteTime(Path.Combine(mapFolderPath, "objects.phxmo")); + + map.FolderPath = mapFolderPath; + // need to do map caching stuff here if (logBenchmark) { @@ -213,34 +217,47 @@ void addAsset(string name, byte[] buffer) public static Map Decode(string path, string audio = null, bool logBenchmark = false, bool save = false) { - if (!File.Exists(path)) + // if (!File.Exists(path)) + // { + // ToastNotification.Notify($"Invalid file path", 2); + // throw Logger.Error($"Invalid file path ({path})"); + // } + + // Extract any .phxm files or encode other formats if needed + if (File.Exists(path)) { - ToastNotification.Notify($"Invalid file path", 2); - throw Logger.Error($"Invalid file path ({path})"); - } + string ext = path.GetExtension(); + double start = Time.GetTicksUsec(); - string ext = path.GetExtension(); - double start = Time.GetTicksUsec(); + if (!IsValidExt(ext)) + { + _ = ToastNotification.Notify("Unsupported file format", 1); + throw Logger.Error($"Unsupported file format ({ext})"); + } + + Map map = ext switch + { + "phxm" => PHXM(path), + "sspm" => SSPM(path), + "txt" => SSMapV1(path, audio), + "rhm" => RHM(path), + _ => new() + }; - if (!IsValidExt(ext)) + if (logBenchmark) Logger.Log($"DECODING {ext.ToUpper()}: {(Time.GetTicksUsec() - start) / 1000}ms"); + if (save) Encode(map); + + return map; + } + else if (Directory.Exists(path)) { - ToastNotification.Notify("Unsupported file format", 1); - throw Logger.Error($"Unsupported file format ({ext})"); + return PHXMFolder(path); } - - Map map = ext switch + else { - "phxm" => PHXM(path), - "sspm" => SSPM(path), - "txt" => SSMapV1(path, audio), - "rhm" => RHM(path), - _ => new() - }; - - if (logBenchmark) Logger.Log($"DECODING {ext.ToUpper()}: {(Time.GetTicksUsec() - start) / 1000}ms"); - if (save) Encode(map); - - return map; + _ = ToastNotification.Notify($"Invalid file path", 2); + throw Logger.Error($"Invalid file path ({path})"); + } } public static Map SSMapV1(string path, string audioPath = null) { @@ -314,7 +331,7 @@ public static Map SSPM(string path) } catch (Exception exception) { - ToastNotification.Notify($"SSPM file corrupted", 2); + _ = ToastNotification.Notify($"SSPM file corrupted", 2); Logger.Error(exception); throw; } @@ -604,42 +621,41 @@ private static Map sspmV2(FileParser file, string path = null) return map; } - public static Map PHXM(string path) + public static Map PHXMFolder(string path) { Map map; try { - var file = ZipFile.OpenRead(path); + GD.Print($"{path}/metadata.json"); + string metadataString = File.ReadAllText($"{path}/metadata.json"); + var metadata = (Dictionary)Json.ParseString(metadataString); + + byte[] objectsBuffer = File.ReadAllBytes($"{path}/objects.phxmo"); - byte[] metaBuffer = getZipEntryBuffer(file, "metadata.json"); - byte[] objectsBuffer = getZipEntryBuffer(file, "objects.phxmo"); byte[] audioBuffer = null; byte[] coverBuffer = null; byte[] videoBuffer = null; - var metadata = (Dictionary)Json.ParseString(Encoding.UTF8.GetString(metaBuffer)); FileParser objects = new(objectsBuffer); if ((bool)metadata["HasAudio"]) { - audioBuffer = getZipEntryBuffer(file, $"audio.{metadata["AudioExt"]}"); + audioBuffer = File.ReadAllBytes($"{path}/audio.{metadata["AudioExt"]}"); } if ((bool)metadata["HasCover"]) { - coverBuffer = getZipEntryBuffer(file, "cover.png"); + coverBuffer = File.ReadAllBytes($"{path}/cover.png"); } if ((bool)metadata["HasVideo"]) { - videoBuffer = getZipEntryBuffer(file, "video.mp4"); + videoBuffer = File.ReadAllBytes($"{path}/video.mp4"); } var notes = DecodePHXMO(objectsBuffer); - file.Dispose(); - // temp metadata.TryGetValue("ArtistLink", out Variant artistLink); metadata.TryGetValue("ArtistPlatform", out Variant artistPlatform); @@ -665,14 +681,92 @@ public static Map PHXM(string path) } catch (Exception exception) { - ToastNotification.Notify($"PHXM file corrupted", 2); + _ = ToastNotification.Notify($"PHXM folder corrupted", 2); Logger.Error(exception); throw; } + GD.Print(map.Title); + return map; } + public static Map PHXM(string path) + { + + string mapDirectory = $"{Constants.USER_FOLDER}/maps"; + + // try + // { + // var file = ZipFile.OpenRead(path); + + // byte[] metaBuffer = getZipEntryBuffer(file, "metadata.json"); + // byte[] objectsBuffer = getZipEntryBuffer(file, "objects.phxmo"); + // byte[] audioBuffer = null; + // byte[] coverBuffer = null; + // byte[] videoBuffer = null; + + // var metadata = (Dictionary)Json.ParseString(Encoding.UTF8.GetString(metaBuffer)); + // FileParser objects = new(objectsBuffer); + + // if ((bool)metadata["HasAudio"]) + // { + // audioBuffer = getZipEntryBuffer(file, $"audio.{metadata["AudioExt"]}"); + // } + + // if ((bool)metadata["HasCover"]) + // { + // coverBuffer = getZipEntryBuffer(file, "cover.png"); + // } + + // if ((bool)metadata["HasVideo"]) + // { + // videoBuffer = getZipEntryBuffer(file, "video.mp4"); + // } + + // var notes = DecodePHXMO(objectsBuffer); + + // file.Dispose(); + + // // temp + // metadata.TryGetValue("ArtistLink", out Variant artistLink); + // metadata.TryGetValue("ArtistPlatform", out Variant artistPlatform); + + // map = new( + // path, + // notes, + // (string)metadata["ID"], + // (string)metadata["Artist"], + // (string)metadata["Title"], + // 0, + // (string[])metadata["Mappers"], + // (int)metadata["Difficulty"], + // (string)metadata["DifficultyName"], + // (int)metadata["Length"], + // audioBuffer, + // coverBuffer, + // videoBuffer, + // false, + // (string)artistLink ?? "", + // (string)artistPlatform ?? "" + // ); + // } + // catch (Exception exception) + // { + // ToastNotification.Notify($"PHXM file corrupted", 2); + // Logger.Error(exception); + // throw; + // } + + string extractedFolderName = Path.GetFileNameWithoutExtension(path); + string extractedFolderPath = Path.Combine(mapDirectory, extractedFolderName); + + ZipFile.ExtractToDirectory(path, extractedFolderPath); + File.Delete(path); + + return PHXMFolder(extractedFolderPath); + } + public static Note[] DecodePHXMO(string path) { FileParser objects = new(path); From f00c7f0f2cc7ea7b8f94c604f1377599c688dbeb Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Tue, 23 Jun 2026 22:52:12 -0400 Subject: [PATCH 11/23] fix .phxm extract --- scripts/map/MapCache.cs | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/scripts/map/MapCache.cs b/scripts/map/MapCache.cs index 7f4e5df8..480f79ba 100644 --- a/scripts/map/MapCache.cs +++ b/scripts/map/MapCache.cs @@ -46,6 +46,7 @@ public static void Load(bool fullSync) if (fullSync) { + GD.Print("full"); syncFiles(toParseMaps); addNonCachedFiles(toParseMaps); @@ -65,6 +66,7 @@ public static void Load(bool fullSync) private static void syncFiles(string[] toParseMaps) { var maps = FetchAll(); + GD.Print("fetched"); FilesToSync.Value = maps.Count; FilesSynced.Value = 0; @@ -78,19 +80,27 @@ private static void syncFiles(string[] toParseMaps) foreach (var map in maps) { + GD.Print($"mapdb = {map.Title}"); + string mapPath = BackSlashToForwardSlash(map.FolderPath); + GD.Print($"HASHSET: {mapsHashSet}, {mapPath}"); + // Checks if the map is actually inside the maps folder if (mapsHashSet.Contains(mapPath)) { + GD.Print("1"); string checksum = GetMd5Checksum(mapPath); + GD.Print($"2: {mapPath}"); DateTime metadataModifiedDate = File.GetLastWriteTime(Path.Combine(mapPath, "metadata.json")); DateTime objectModifiedDate = File.GetLastWriteTime(Path.Combine(mapPath, "objects.phxmo")); + GD.Print("3"); GD.Print($"{Path.Combine(mapPath, "metadata.json")} = {metadataModifiedDate}"); bool metadataCheck = metadataModifiedDate == map.LastModifiedMetadata; bool objectsCheck = objectModifiedDate == map.LastModifiedNotes; + GD.Print("4"); if (map.MetadataObjectHash == checksum || metadataCheck || objectsCheck) { @@ -98,12 +108,16 @@ private static void syncFiles(string[] toParseMaps) FilesSynced.Value += 1; continue; } + GD.Print("5"); Map newMap; + GD.Print("dfdsjlkfdjsf"); + try { newMap = MapParser.Decode(mapPath, null, false, true); + GD.Print($"NEW MAPTITLE: {newMap.Title}"); } catch (Exception ex) { @@ -137,14 +151,13 @@ private static void syncFiles(string[] toParseMaps) else { // removeCacheFolder(map); - try + GD.Print("MAP NOT FOUND!"); + + if (Directory.Exists($"{MapUtil.MapsFolder}/{map.Name}")) { Directory.Delete($"{MapUtil.MapsFolder}/{map.Name}", true); } - catch - { - return; - } + DatabaseService.Connection.Delete(map); Logger.Log($"Removed {mapPath} from the cache, as it no longer exists."); @@ -229,11 +242,15 @@ private static void addNonCachedFiles(string[] toParseMaps) try { + GD.Print("new map!"); var map = MapParser.Decode(toParseMap); + GD.Print($"map decoded!: {map.Name}"); // var map = !Directory.Exists(file) ? MapParser.Decode(file) : MapParser.DecodeFolder(file); map.FolderPath = $"{Constants.USER_FOLDER}/maps/{map.Name}"; + GD.Print($"folder pathed! hashing: {toParseMap}"); // map.FilePath = !Directory.Exists(map.FilePath) ? $"{Constants.USER_FOLDER}/maps/{map.Name}.{Constants.DEFAULT_MAP_EXT}" : $"{Constants.USER_FOLDER}/maps/{map.Name}"; - map.MetadataObjectHash = GetMd5Checksum(toParseMap); + map.MetadataObjectHash = GetMd5Checksum(map.FolderPath); + GD.Print("inserting"); InsertMap(map); } catch @@ -248,9 +265,12 @@ private static void addNonCachedFiles(string[] toParseMaps) public static int InsertMap(Map map) { + GD.Print("insert received!"); var existing = DatabaseService.Connection.Find(x => x.MetadataObjectHash == map.MetadataObjectHash); var updated = DatabaseService.Connection.Find(x => x.Name == map.Name); + GD.Print($"existing: {existing}, updated: {updated}"); + try { if (updated != null && existing != null) @@ -389,9 +409,13 @@ public static void OrderAndSetMaps() public static string GetMd5Checksum(string path) { + GD.Print($"hi from hash! path: {path}"); string metadataPath = Path.Combine(path, "metadata.json"); + GD.Print("meta hash!"); string objectsPath = Path.Combine(path, "objects.phxmo"); + GD.Print("objects hash!"); byte[] hash = Misc.HashFiles([metadataPath, objectsPath]); + GD.Print("returning hash!"); return BitConverter.ToString(hash).Replace("-", string.Empty).ToLower(); From c85a6da94434f1eda38d5f6637f0522da164ae41 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Tue, 23 Jun 2026 22:52:32 -0400 Subject: [PATCH 12/23] more debug YAY!!!! --- scripts/map/MapParser.cs | 6 ++++-- scripts/util/Misc.cs | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/scripts/map/MapParser.cs b/scripts/map/MapParser.cs index 572ef7b9..5b91a12e 100644 --- a/scripts/map/MapParser.cs +++ b/scripts/map/MapParser.cs @@ -26,6 +26,9 @@ public override void _Ready() public static async Task BulkImport(string[] files, bool notify = false) { + + GD.Print("HELLO FROM BULK!"); + if (files.Length == 0 || files == null) return; if (notify) _ = ToastNotification.Notify($"Importing {files.Length} map(s)"); @@ -627,7 +630,6 @@ public static Map PHXMFolder(string path) try { - GD.Print($"{path}/metadata.json"); string metadataString = File.ReadAllText($"{path}/metadata.json"); var metadata = (Dictionary)Json.ParseString(metadataString); @@ -686,7 +688,7 @@ public static Map PHXMFolder(string path) throw; } - GD.Print(map.Title); + GD.Print($"HI FROM DECODER! Heres the name: {map.Name}"); return map; } diff --git a/scripts/util/Misc.cs b/scripts/util/Misc.cs index 510bfa2c..d8602b2a 100644 --- a/scripts/util/Misc.cs +++ b/scripts/util/Misc.cs @@ -67,16 +67,29 @@ public static void CopyProperties(Node node, Node reference) public static byte[] HashFiles(string[] paths) { + GD.Print("hi from hashfiles"); using var md5 = MD5.Create(); + GD.Print($"created hash, heres the paths! {paths[0]}"); - foreach (var path in paths) // we do not need to order the paths since it will always be the same -fog + foreach (string path in paths) // we do not need to order the paths since it will always be the same -fog { + GD.Print($"HASH PRINT!: {path}"); + GD.Print($"Exists: {File.Exists(path)}"); + + var info = new FileInfo(path); + GD.Print($"Length: {info.Length}"); byte[] fileData = File.ReadAllBytes(path); + GD.Print($"Read {fileData.Length} bytes"); md5.TransformBlock(fileData, 0, fileData.Length, null, 0); + GD.Print("Transformed"); } + GD.Print("final hash"); + md5.TransformFinalBlock(Array.Empty(), 0 ,0); + GD.Print("returning final hash"); + return md5.Hash; } From bfd70207b42c2efb87f6deea5dcdded13713c435 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Thu, 25 Jun 2026 06:01:53 -0400 Subject: [PATCH 13/23] fix --- scripts/map/MapManager.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/map/MapManager.cs b/scripts/map/MapManager.cs index 6d5c0d5e..e9986566 100644 --- a/scripts/map/MapManager.cs +++ b/scripts/map/MapManager.cs @@ -39,9 +39,14 @@ public static void Select(Map map) Selected.Value = GetMapById(map.Id); } + // public static Map GetMapById(int id) + // { + // return Maps.Where(x => x.Id == id).First(); + // } + public static Map GetMapById(int id) { - return Maps.Where(x => x.Id == id).First(); + return Maps.FirstOrDefault(x => x.Id == id); } public static void Update(Map map) From a79487a8dc4968dd25531bef283e135e31272fa4 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Fri, 26 Jun 2026 00:44:32 -0400 Subject: [PATCH 14/23] yeah! --- scripts/map/Map.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/map/Map.cs b/scripts/map/Map.cs index 118b97a0..afbb3638 100644 --- a/scripts/map/Map.cs +++ b/scripts/map/Map.cs @@ -17,8 +17,8 @@ public partial class Map : RefCounted public int Id { get; set; } public string Name { get; set; } = string.Empty; - public DateTime LastModifiedMetadata { get; set; } - public DateTime LastModifiedNotes { get; set; } + public string LastModifiedMetadata { get; set; } + public string LastModifiedNotes { get; set; } /// /// The hash of the metadata.json, then the objects.phxmo in order @@ -120,10 +120,13 @@ private Texture2D getCover() public Map() { } - public Map(string folderPath, Note[] data = null, string id = null, string artist = "", string title = "", float rating = 0, string[] mappers = null, int difficulty = 0, string difficultyName = null, int? length = null, byte[] audioBuffer = null, byte[] coverBuffer = null, byte[] videoBuffer = null, bool ephemeral = false, string artistLink = "", string artistPlatform = "") + public Map(string folderPath, string metadataObjHash = "", string lastModifiedMetadata = "", string lastModifiedNotes = "", Note[] data = null, string id = null, string artist = "", string title = "", float rating = 0, string[] mappers = null, int difficulty = 0, string difficultyName = null, int? length = null, byte[] audioBuffer = null, byte[] coverBuffer = null, byte[] videoBuffer = null, bool ephemeral = false, string artistLink = "", string artistPlatform = "") { FolderPath = folderPath; Ephemeral = ephemeral; + MetadataObjectHash = metadataObjHash; + LastModifiedMetadata = lastModifiedMetadata; + LastModifiedNotes = lastModifiedNotes; Artist = (artist ?? "").StripEscapes(); ArtistLink = artistLink; ArtistPlatform = artistPlatform; From 775379e024c945385b2893b1179103d0e2bbbe5c Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Fri, 26 Jun 2026 00:45:24 -0400 Subject: [PATCH 15/23] small optimization --- scripts/map/MapCache.cs | 60 +++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/scripts/map/MapCache.cs b/scripts/map/MapCache.cs index 480f79ba..ccbe4d4b 100644 --- a/scripts/map/MapCache.cs +++ b/scripts/map/MapCache.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.IO; using System.IO.Compression; @@ -46,7 +47,6 @@ public static void Load(bool fullSync) if (fullSync) { - GD.Print("full"); syncFiles(toParseMaps); addNonCachedFiles(toParseMaps); @@ -66,7 +66,6 @@ public static void Load(bool fullSync) private static void syncFiles(string[] toParseMaps) { var maps = FetchAll(); - GD.Print("fetched"); FilesToSync.Value = maps.Count; FilesSynced.Value = 0; @@ -80,44 +79,49 @@ private static void syncFiles(string[] toParseMaps) foreach (var map in maps) { - GD.Print($"mapdb = {map.Title}"); string mapPath = BackSlashToForwardSlash(map.FolderPath); - GD.Print($"HASHSET: {mapsHashSet}, {mapPath}"); - // Checks if the map is actually inside the maps folder if (mapsHashSet.Contains(mapPath)) { - GD.Print("1"); - string checksum = GetMd5Checksum(mapPath); - GD.Print($"2: {mapPath}"); DateTime metadataModifiedDate = File.GetLastWriteTime(Path.Combine(mapPath, "metadata.json")); DateTime objectModifiedDate = File.GetLastWriteTime(Path.Combine(mapPath, "objects.phxmo")); - GD.Print("3"); - GD.Print($"{Path.Combine(mapPath, "metadata.json")} = {metadataModifiedDate}"); + // i have to convert to string since sqlite doesnt support DateTime c# conversion + // PLUS, theres like seconds or something and it doesnt catch that soooooo + string metadataResult = metadataModifiedDate.ToString(); + string notesResult = objectModifiedDate.ToString(); + + bool metadataCheck = map.LastModifiedMetadata == metadataResult; + bool objectsCheck = map.LastModifiedNotes == notesResult; - bool metadataCheck = metadataModifiedDate == map.LastModifiedMetadata; - bool objectsCheck = objectModifiedDate == map.LastModifiedNotes; - GD.Print("4"); + // GD.Print($"{Path.Combine(mapPath, "metadata.json")} = {map.LastModifiedMetadata},{metadataCheck}"); + // GD.Print($"{Path.Combine(mapPath, "metadata.json")} = {metadataResult},{objectsCheck}"); - if (map.MetadataObjectHash == checksum || metadataCheck || objectsCheck) + // last modified is faster and lowkey more important -fog + if (metadataCheck || objectsCheck) { GD.Print("skip"); - FilesSynced.Value += 1; + FilesSynced.Value++; continue; } - GD.Print("5"); - Map newMap; + // we will do checksum checking after if last modified dates dont match + // this code shouldn't be reached unless the dates dont match + string checksum = GetMd5Checksum(mapPath); + if (map.MetadataObjectHash == checksum) + { + GD.Print("skip, but with hash"); + FilesSynced.Value++; + continue; + } - GD.Print("dfdsjlkfdjsf"); + Map newMap; try { newMap = MapParser.Decode(mapPath, null, false, true); - GD.Print($"NEW MAPTITLE: {newMap.Title}"); } catch (Exception ex) { @@ -136,8 +140,8 @@ private static void syncFiles(string[] toParseMaps) continue; } - newMap.LastModifiedMetadata = metadataModifiedDate; - newMap.LastModifiedNotes = objectModifiedDate; + newMap.LastModifiedMetadata = metadataModifiedDate.ToString(); + newMap.LastModifiedNotes = objectModifiedDate.ToString(); newMap.Id = map.Id; newMap.MetadataObjectHash = checksum; @@ -150,9 +154,6 @@ private static void syncFiles(string[] toParseMaps) } else { - // removeCacheFolder(map); - GD.Print("MAP NOT FOUND!"); - if (Directory.Exists($"{MapUtil.MapsFolder}/{map.Name}")) { Directory.Delete($"{MapUtil.MapsFolder}/{map.Name}", true); @@ -242,15 +243,11 @@ private static void addNonCachedFiles(string[] toParseMaps) try { - GD.Print("new map!"); var map = MapParser.Decode(toParseMap); - GD.Print($"map decoded!: {map.Name}"); // var map = !Directory.Exists(file) ? MapParser.Decode(file) : MapParser.DecodeFolder(file); map.FolderPath = $"{Constants.USER_FOLDER}/maps/{map.Name}"; - GD.Print($"folder pathed! hashing: {toParseMap}"); // map.FilePath = !Directory.Exists(map.FilePath) ? $"{Constants.USER_FOLDER}/maps/{map.Name}.{Constants.DEFAULT_MAP_EXT}" : $"{Constants.USER_FOLDER}/maps/{map.Name}"; map.MetadataObjectHash = GetMd5Checksum(map.FolderPath); - GD.Print("inserting"); InsertMap(map); } catch @@ -265,12 +262,9 @@ private static void addNonCachedFiles(string[] toParseMaps) public static int InsertMap(Map map) { - GD.Print("insert received!"); var existing = DatabaseService.Connection.Find(x => x.MetadataObjectHash == map.MetadataObjectHash); var updated = DatabaseService.Connection.Find(x => x.Name == map.Name); - GD.Print($"existing: {existing}, updated: {updated}"); - try { if (updated != null && existing != null) @@ -409,13 +403,9 @@ public static void OrderAndSetMaps() public static string GetMd5Checksum(string path) { - GD.Print($"hi from hash! path: {path}"); string metadataPath = Path.Combine(path, "metadata.json"); - GD.Print("meta hash!"); string objectsPath = Path.Combine(path, "objects.phxmo"); - GD.Print("objects hash!"); byte[] hash = Misc.HashFiles([metadataPath, objectsPath]); - GD.Print("returning hash!"); return BitConverter.ToString(hash).Replace("-", string.Empty).ToLower(); From f88717bc64d346c984c500a81f4b5dce2a6cfba5 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Fri, 26 Jun 2026 00:45:53 -0400 Subject: [PATCH 16/23] cleanup + fix --- scripts/map/MapParser.cs | 94 +++++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/scripts/map/MapParser.cs b/scripts/map/MapParser.cs index 5b91a12e..1580425f 100644 --- a/scripts/map/MapParser.cs +++ b/scripts/map/MapParser.cs @@ -26,9 +26,6 @@ public override void _Ready() public static async Task BulkImport(string[] files, bool notify = false) { - - GD.Print("HELLO FROM BULK!"); - if (files.Length == 0 || files == null) return; if (notify) _ = ToastNotification.Notify($"Importing {files.Length} map(s)"); @@ -155,38 +152,40 @@ public static void Encode(Map map, bool logBenchmark = false) File.WriteAllText(Path.Combine(mapFolderPath, "metadata.json"), map.EncodeMeta()); using var stream = File.Create(Path.Combine(mapFolderPath, "objects.phxmo")); - using BinaryWriter bw = new BinaryWriter(stream); - - bw.Write((uint)12); - bw.Write((uint)map.Notes.Length); - foreach (var note in map.Notes) + // using BinaryWriter bw = new BinaryWriter(stream); + using (var bw = new BinaryWriter(stream)) { - bool quantum = (int)note.X != note.X || (int)note.Y != note.Y || note.X < -1 || note.X > 1 || note.Y < -1 || note.Y > 1; - bw.Write((uint)note.Millisecond); - bw.Write(Convert.ToByte(quantum)); - if (quantum) - { - bw.Write((float)note.X); - bw.Write((float)note.Y); - } - else - { - bw.Write((byte)(note.X + 1)); - bw.Write((byte)(note.Y + 1)); + bw.Write((uint)12); + bw.Write((uint)map.Notes.Length); + foreach (var note in map.Notes) + { + bool quantum = (int)note.X != note.X || (int)note.Y != note.Y || note.X < -1 || note.X > 1 || note.Y < -1 || note.Y > 1; + bw.Write((uint)note.Millisecond); + bw.Write(Convert.ToByte(quantum)); + if (quantum) + { + bw.Write((float)note.X); + bw.Write((float)note.Y); + } + else + { + bw.Write((byte)(note.X + 1)); + bw.Write((byte)(note.Y + 1)); + } } - } - bw.Write(0); // timing point count - bw.Write(0); // brightness count - bw.Write(0); // contrast count - bw.Write(0); // saturation count - bw.Write(0); // blur count - bw.Write(0); // fov count - bw.Write(0); // tint count - bw.Write(0); // position count - bw.Write(0); // rotation count - bw.Write(0); // ar factor count - bw.Write(0); // text count + bw.Write(0); // timing point count + bw.Write(0); // brightness count + bw.Write(0); // contrast count + bw.Write(0); // saturation count + bw.Write(0); // blur count + bw.Write(0); // fov count + bw.Write(0); // tint count + bw.Write(0); // position count + bw.Write(0); // rotation count + bw.Write(0); // ar factor count + bw.Write(0); // text count + } void addAsset(string name, byte[] buffer) { @@ -206,8 +205,11 @@ void addAsset(string name, byte[] buffer) map.MetadataObjectHash = BitConverter.ToString(hash).Replace("-", "").ToLower(); - map.LastModifiedMetadata = File.GetLastWriteTime(Path.Combine(mapFolderPath, "metadata.json")); - map.LastModifiedNotes = File.GetLastWriteTime(Path.Combine(mapFolderPath, "objects.phxmo")); + + DateTime metadataModified = File.GetLastWriteTime(Path.Combine(mapFolderPath, "metadata.json")); + DateTime objectsModified = File.GetLastWriteTime(Path.Combine(mapFolderPath, "objects.phxmo")); + map.LastModifiedMetadata = metadataModified.ToString(); + map.LastModifiedNotes = objectsModified.ToString(); map.FolderPath = mapFolderPath; // need to do map caching stuff here @@ -290,7 +292,7 @@ public static Map SSMapV1(string path, string audioPath = null) audio.Close(); } - map = new(path, notes, null, "", name, audioBuffer: audioBuffer); + map = new(path, "", "", "", notes, null, "", name, audioBuffer: audioBuffer); } catch (Exception exception) { @@ -458,7 +460,7 @@ private static Map sspmV1(FileParser file, string path = null) notes[i].Index = i; } - map = new(path ?? $"{Constants.USER_FOLDER}/maps/{song}_temp.sspm", notes, id, artist, song, 0, mappers, difficulty, null, (int)mapLength, audioBuffer, coverBuffer); + map = new(path ?? $"{Constants.USER_FOLDER}/maps/{song}_temp.sspm", "", "", "", notes, id, artist, song, 0, mappers, difficulty, null, (int)mapLength, audioBuffer, coverBuffer); } catch (Exception exception) { @@ -612,7 +614,7 @@ private static Map sspmV2(FileParser file, string path = null) notes[i].Index = i; } - map = new(path, notes, id, artist, song, 0, mappers, difficulty, difficultyName, (int)mapLength, audioBuffer, coverBuffer); + map = new(path, "", "", "", notes, id, artist, song, 0, mappers, difficulty, difficultyName, (int)mapLength, audioBuffer, coverBuffer); } catch (Exception exception) { @@ -639,7 +641,7 @@ public static Map PHXMFolder(string path) byte[] coverBuffer = null; byte[] videoBuffer = null; - FileParser objects = new(objectsBuffer); + // FileParser objects = new(objectsBuffer); if ((bool)metadata["HasAudio"]) { @@ -662,8 +664,19 @@ public static Map PHXMFolder(string path) metadata.TryGetValue("ArtistLink", out Variant artistLink); metadata.TryGetValue("ArtistPlatform", out Variant artistPlatform); + + + byte[] hash = Misc.HashFiles([Path.Combine(path, "metadata.json"), Path.Combine(path, "objects.phxmo")]); + + DateTime metadataModified = File.GetLastWriteTime(Path.Combine(path, "metadata.json")); + DateTime objectsModified = File.GetLastWriteTime(Path.Combine(path, "objects.phxmo")); + + map = new( path, + BitConverter.ToString(hash).Replace("-", "").ToLower(), + metadataModified.ToString(), + objectsModified.ToString(), notes, (string)metadata["ID"], (string)metadata["Artist"], @@ -687,8 +700,6 @@ public static Map PHXMFolder(string path) Logger.Error(exception); throw; } - - GD.Print($"HI FROM DECODER! Heres the name: {map.Name}"); return map; } @@ -856,6 +867,9 @@ public static Map RHM(string path) map = new( path, + "", + "", + "", notes, null, artist ?? "", From e60c1aa0f5134e0f42089d5faf5057815df80bee Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Fri, 26 Jun 2026 00:46:05 -0400 Subject: [PATCH 17/23] cleanupppppp --- scripts/map/MapManager.cs | 6 +----- scripts/util/Misc.cs | 13 ------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/scripts/map/MapManager.cs b/scripts/map/MapManager.cs index e9986566..7f09461c 100644 --- a/scripts/map/MapManager.cs +++ b/scripts/map/MapManager.cs @@ -39,13 +39,9 @@ public static void Select(Map map) Selected.Value = GetMapById(map.Id); } - // public static Map GetMapById(int id) - // { - // return Maps.Where(x => x.Id == id).First(); - // } - public static Map GetMapById(int id) { + // return Maps.Where(x => x.Id == id).First(); return Maps.FirstOrDefault(x => x.Id == id); } diff --git a/scripts/util/Misc.cs b/scripts/util/Misc.cs index d8602b2a..3f882c06 100644 --- a/scripts/util/Misc.cs +++ b/scripts/util/Misc.cs @@ -67,29 +67,16 @@ public static void CopyProperties(Node node, Node reference) public static byte[] HashFiles(string[] paths) { - GD.Print("hi from hashfiles"); using var md5 = MD5.Create(); - GD.Print($"created hash, heres the paths! {paths[0]}"); foreach (string path in paths) // we do not need to order the paths since it will always be the same -fog { - GD.Print($"HASH PRINT!: {path}"); - GD.Print($"Exists: {File.Exists(path)}"); - - var info = new FileInfo(path); - GD.Print($"Length: {info.Length}"); byte[] fileData = File.ReadAllBytes(path); - GD.Print($"Read {fileData.Length} bytes"); md5.TransformBlock(fileData, 0, fileData.Length, null, 0); - GD.Print("Transformed"); } - GD.Print("final hash"); - md5.TransformFinalBlock(Array.Empty(), 0 ,0); - GD.Print("returning final hash"); - return md5.Hash; } From f036bdcce5637a77efb177e5df4f780b481c9d36 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Sun, 28 Jun 2026 02:07:42 -0400 Subject: [PATCH 18/23] its as shrimple as that --- scripts/map/MapParser.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/map/MapParser.cs b/scripts/map/MapParser.cs index 1580425f..cc760637 100644 --- a/scripts/map/MapParser.cs +++ b/scripts/map/MapParser.cs @@ -214,6 +214,8 @@ void addAsset(string name, byte[] buffer) map.FolderPath = mapFolderPath; // need to do map caching stuff here + MapCache.InsertMap(map); + if (logBenchmark) { Logger.Log($"ENCODING {Constants.DEFAULT_MAP_EXT.ToUpper()}: {(Time.GetTicksUsec() - start) / 1000}ms"); @@ -260,8 +262,8 @@ public static Map Decode(string path, string audio = null, bool logBenchmark = f } else { - _ = ToastNotification.Notify($"Invalid file path", 2); - throw Logger.Error($"Invalid file path ({path})"); + _ = ToastNotification.Notify($"Invalid map path", 2); + throw Logger.Error($"Invalid map path ({path})"); } } public static Map SSMapV1(string path, string audioPath = null) From 16d8de8b17fa5c872516f9c29052814a89c9aad0 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Sun, 28 Jun 2026 02:07:50 -0400 Subject: [PATCH 19/23] djfodsjfoisdfjhiosfjhoisdf --- scripts/map/MapCache.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/map/MapCache.cs b/scripts/map/MapCache.cs index ccbe4d4b..58bd0a40 100644 --- a/scripts/map/MapCache.cs +++ b/scripts/map/MapCache.cs @@ -354,7 +354,6 @@ public static void OrderAndSetMaps() } }).CallDeferred(); } - } } }); From 3a1df8b004c49653b509030360913c960e82343c Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Sun, 28 Jun 2026 03:40:04 -0400 Subject: [PATCH 20/23] cleanup + fix loading --- scripts/map/MapCache.cs | 44 ++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/scripts/map/MapCache.cs b/scripts/map/MapCache.cs index 58bd0a40..b5f2ba04 100644 --- a/scripts/map/MapCache.cs +++ b/scripts/map/MapCache.cs @@ -79,7 +79,7 @@ private static void syncFiles(string[] toParseMaps) foreach (var map in maps) { - + string mapPath = BackSlashToForwardSlash(map.FolderPath); // Checks if the map is actually inside the maps folder @@ -96,13 +96,9 @@ private static void syncFiles(string[] toParseMaps) bool metadataCheck = map.LastModifiedMetadata == metadataResult; bool objectsCheck = map.LastModifiedNotes == notesResult; - // GD.Print($"{Path.Combine(mapPath, "metadata.json")} = {map.LastModifiedMetadata},{metadataCheck}"); - // GD.Print($"{Path.Combine(mapPath, "metadata.json")} = {metadataResult},{objectsCheck}"); - // last modified is faster and lowkey more important -fog if (metadataCheck || objectsCheck) { - GD.Print("skip"); FilesSynced.Value++; continue; } @@ -112,7 +108,6 @@ private static void syncFiles(string[] toParseMaps) string checksum = GetMd5Checksum(mapPath); if (map.MetadataObjectHash == checksum) { - GD.Print("skip, but with hash"); FilesSynced.Value++; continue; } @@ -136,7 +131,7 @@ private static void syncFiles(string[] toParseMaps) } DatabaseService.Connection.Delete(map); - FilesSynced.Value += 1; + FilesSynced.Value++; continue; } @@ -149,7 +144,7 @@ private static void syncFiles(string[] toParseMaps) DatabaseService.Connection.Update(newMap); // InsertIntoMapCacheFolder(map); Logger.Log($"Updated cached map: {newMap.Name}"); - FilesSynced.Value += 1; + FilesSynced.Value++; continue; } else @@ -232,6 +227,8 @@ private static void addNonCachedFiles(string[] toParseMaps) HashSet hashSet = new(); maps.ForEach(map => hashSet.Add(map.FolderPath)); + FilesToSync.Value = toParseMaps.Count() - maps.Count(); + foreach (string toParseMap in toParseMaps) { if (hashSet.Contains(BackSlashToForwardSlash(toParseMap))) @@ -239,14 +236,12 @@ private static void addNonCachedFiles(string[] toParseMaps) continue; } - FilesToSync.Value += 1; + // FilesToSync.Value += 1; try { var map = MapParser.Decode(toParseMap); - // var map = !Directory.Exists(file) ? MapParser.Decode(file) : MapParser.DecodeFolder(file); map.FolderPath = $"{Constants.USER_FOLDER}/maps/{map.Name}"; - // map.FilePath = !Directory.Exists(map.FilePath) ? $"{Constants.USER_FOLDER}/maps/{map.Name}.{Constants.DEFAULT_MAP_EXT}" : $"{Constants.USER_FOLDER}/maps/{map.Name}"; map.MetadataObjectHash = GetMd5Checksum(map.FolderPath); InsertMap(map); } @@ -417,6 +412,33 @@ public static string GetMd5Checksum(string path) // } } + // public static int GetMapCount(List maps, string[] mapFiles) + // { + // int map_count = 0; + + // HashSet hashSet = new(); + // maps.ForEach(map => hashSet.Add(map.FolderPath)); + + + + // foreach (string map_entry in mapFiles) + // { + // if (File.Exists(map_entry)) + // { + // map_count++; + // } + // else if (Directory.Exists(map_entry)) + // { + // if (hashSet.Contains(BackSlashToForwardSlash($"{MapUtil.MapsFolder}/{map_entry}"))) + // { + // map_count++; + // } + // } + // } + + // return map_count; + // } + public static List FetchAll() => DatabaseService.Connection.Table().ToList(); public static string BackSlashToForwardSlash(string path) => path.Replace("\\", "/"); From c9f4b6bc84d30c4496ea8032fae4692545981f04 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Sun, 28 Jun 2026 04:12:07 -0400 Subject: [PATCH 21/23] more cleanup --- scripts/map/MapCache.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/map/MapCache.cs b/scripts/map/MapCache.cs index b5f2ba04..ee72206e 100644 --- a/scripts/map/MapCache.cs +++ b/scripts/map/MapCache.cs @@ -79,7 +79,7 @@ private static void syncFiles(string[] toParseMaps) foreach (var map in maps) { - + string mapPath = BackSlashToForwardSlash(map.FolderPath); // Checks if the map is actually inside the maps folder @@ -157,7 +157,7 @@ private static void syncFiles(string[] toParseMaps) DatabaseService.Connection.Delete(map); Logger.Log($"Removed {mapPath} from the cache, as it no longer exists."); - FilesSynced.Value += 1; + FilesSynced.Value++; } } } @@ -251,7 +251,7 @@ private static void addNonCachedFiles(string[] toParseMaps) Logger.Log($"Failed to add map non-cached map"); } - FilesSynced.Value += 1; + FilesSynced.Value++; } } From db3954661f94a8a09cfc73ffabb8cef9e8ec14e5 Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Sun, 28 Jun 2026 12:54:25 -0400 Subject: [PATCH 22/23] fix replace map bug --- scripts/map/MapCache.cs | 106 ++++----------------------------------- scripts/map/MapParser.cs | 8 +++ 2 files changed, 18 insertions(+), 96 deletions(-) diff --git a/scripts/map/MapCache.cs b/scripts/map/MapCache.cs index ee72206e..cba136b7 100644 --- a/scripts/map/MapCache.cs +++ b/scripts/map/MapCache.cs @@ -39,9 +39,13 @@ public static void Load(bool fullSync) // .ToList(); // Map files go first since they will be encoded to folders after they get parsed in MapParser.cs - List mapsList = Directory.GetDirectories(MapUtil.MapsFolder, "*", SearchOption.AllDirectories) - .Concat(Directory.GetFiles(MapUtil.MapsFolder,$"*.{Constants.DEFAULT_MAP_EXT}", SearchOption.AllDirectories)) - .ToList(); + List mapsList = Directory.GetFiles(MapUtil.MapsFolder,$"*.{Constants.DEFAULT_MAP_EXT}", SearchOption.AllDirectories) + .Concat(Directory.GetDirectories(MapUtil.MapsFolder, "*", SearchOption.AllDirectories)) + .ToList(); + + // List mapsList = Directory.GetDirectories(MapUtil.MapsFolder, "*", SearchOption.AllDirectories) + // .Concat(Directory.GetFiles(MapUtil.MapsFolder,$"*.{Constants.DEFAULT_MAP_EXT}", SearchOption.AllDirectories)) + // .ToList(); string[] toParseMaps = mapsList.ToArray(); @@ -162,64 +166,6 @@ private static void syncFiles(string[] toParseMaps) } } - // public static void InsertIntoMapCacheFolder(Map map) - // { - // string path = $"{MapUtil.MapsCacheFolder}/{map.Name}"; - - // // for phxm shit i guess - // if (File.Exists(map.FolderPath)) - // { - // using var stream = File.OpenRead(map.FolderPath); - // var archive = new ZipArchive(stream); - - // if (Directory.Exists(path)) - // { - // Directory.Delete(path, true); - // } - - // archive.ExtractToDirectory(path, true); - // } - // else if (Directory.Exists(map.FolderPath)) - // { - // GD.Print("PATH PATH PATH!!!"); - // if (Directory.Exists(path)) - // { - // Directory.Delete(path, true); - // } - - // Directory.CreateDirectory(path); - - // foreach (string file in Directory.GetFiles(map.FolderPath)) - // { - // string destFile = Path.Combine(path, Path.GetFileName(file)); - // File.Copy(file, destFile, overwrite: true); - // } - // } - - // // using var stream = File.OpenRead(map.FilePath); - // // var archive = new ZipArchive(stream); - - // // if (Directory.Exists(path)) - // // { - // // Directory.Delete(path, true); - // // } - - // // archive.ExtractToDirectory(path, true); - - // } - - // private static void removeCacheFolder(Map map) - // { - // try - // { - // Directory.Delete($"{MapUtil.MapsCacheFolder}/{map.Name}", true); - // } - // catch - // { - // return; - // } - // } - private static void addNonCachedFiles(string[] toParseMaps) { var maps = FetchAll(); @@ -227,7 +173,9 @@ private static void addNonCachedFiles(string[] toParseMaps) HashSet hashSet = new(); maps.ForEach(map => hashSet.Add(map.FolderPath)); + // Maps that need to be parsed - maps in database cache FilesToSync.Value = toParseMaps.Count() - maps.Count(); + FilesSynced.Value = 0; foreach (string toParseMap in toParseMaps) { @@ -240,6 +188,7 @@ private static void addNonCachedFiles(string[] toParseMaps) try { + GD.Print($"decoding: {toParseMap}\nfilestosync: {FilesToSync.Value}, filessynced: {FilesSynced.Value}"); var map = MapParser.Decode(toParseMap); map.FolderPath = $"{Constants.USER_FOLDER}/maps/{map.Name}"; map.MetadataObjectHash = GetMd5Checksum(map.FolderPath); @@ -402,43 +351,8 @@ public static string GetMd5Checksum(string path) byte[] hash = Misc.HashFiles([metadataPath, objectsPath]); return BitConverter.ToString(hash).Replace("-", string.Empty).ToLower(); - - // using (var md5 = MD5.Create()) - // { - // using (var stream = File.OpenRead(path)) - // { - // return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", string.Empty).ToLower(); - // } - // } } - // public static int GetMapCount(List maps, string[] mapFiles) - // { - // int map_count = 0; - - // HashSet hashSet = new(); - // maps.ForEach(map => hashSet.Add(map.FolderPath)); - - - - // foreach (string map_entry in mapFiles) - // { - // if (File.Exists(map_entry)) - // { - // map_count++; - // } - // else if (Directory.Exists(map_entry)) - // { - // if (hashSet.Contains(BackSlashToForwardSlash($"{MapUtil.MapsFolder}/{map_entry}"))) - // { - // map_count++; - // } - // } - // } - - // return map_count; - // } - public static List FetchAll() => DatabaseService.Connection.Table().ToList(); public static string BackSlashToForwardSlash(string path) => path.Replace("\\", "/"); diff --git a/scripts/map/MapParser.cs b/scripts/map/MapParser.cs index cc760637..06854e67 100644 --- a/scripts/map/MapParser.cs +++ b/scripts/map/MapParser.cs @@ -630,6 +630,7 @@ private static Map sspmV2(FileParser file, string path = null) public static Map PHXMFolder(string path) { + Map map; try @@ -776,6 +777,13 @@ public static Map PHXM(string path) string extractedFolderName = Path.GetFileNameWithoutExtension(path); string extractedFolderPath = Path.Combine(mapDirectory, extractedFolderName); + if (Directory.Exists(extractedFolderPath)) + { + Directory.Delete(extractedFolderPath, true); // true = recursive + Map existingMap = DatabaseService.Connection.Table().FirstOrDefault(x => x.FolderPath == extractedFolderPath); + MapCache.RemoveMap(existingMap); + } + ZipFile.ExtractToDirectory(path, extractedFolderPath); File.Delete(path); From 8688ebf788de1cc51073e6513a77ec36bb5b08eb Mon Sep 17 00:00:00 2001 From: fogsaturate Date: Sun, 28 Jun 2026 13:06:17 -0400 Subject: [PATCH 23/23] fix replays --- scripts/game/managers/ReplayManager.cs | 2 +- scripts/map/Replay.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/game/managers/ReplayManager.cs b/scripts/game/managers/ReplayManager.cs index 631e5332..ae3d0269 100644 --- a/scripts/game/managers/ReplayManager.cs +++ b/scripts/game/managers/ReplayManager.cs @@ -73,7 +73,7 @@ public void NewReplay(Attempt attempt) string serializedMods = string.Join("_", mods); // string mapName = attempt.Map.FilePath.GetFile().GetBaseName(); - string mapName = Path.GetDirectoryName(attempt.Map.FolderPath); + string mapName = Path.GetFileName(attempt.Map.FolderPath); string player = "You"; void storeSizedString(string data) diff --git a/scripts/map/Replay.cs b/scripts/map/Replay.cs index a2764ed6..4e180900 100644 --- a/scripts/map/Replay.cs +++ b/scripts/map/Replay.cs @@ -168,13 +168,14 @@ public Replay(string path) MapID = FileBuffer.GetString((int)FileBuffer.GetUInt32()); MapNoteCount = FileBuffer.GetUInt64(); - MapFilePath = $"{Constants.USER_FOLDER}/maps/{MapID}.phxm"; + MapFilePath = $"{Constants.USER_FOLDER}/maps/{MapID}"; + MapFilePath = Path.GetFileNameWithoutExtension(MapFilePath); // just in case it tries to read a .phxm file - if (!File.Exists(MapFilePath)) + if (!Directory.Exists(MapFilePath)) { Valid = false; ToastNotification.Notify("Replay map not found", 2); - Logger.Log($"Replay map not found, path: {MapFilePath}.phxm"); + Logger.Log($"Replay map not found, path: {MapFilePath}"); return; }