diff --git a/ModAssistant/App.config b/ModAssistant/App.config index 7a673b8e..c08719a4 100644 --- a/ModAssistant/App.config +++ b/ModAssistant/App.config @@ -1,10 +1,11 @@ - + - +
+
@@ -69,4 +70,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModAssistant/Classes/External Interfaces/BeatSaver.cs b/ModAssistant/Classes/External Interfaces/BeatSaver.cs index 0f9a3af4..3ea40c5b 100644 --- a/ModAssistant/Classes/External Interfaces/BeatSaver.cs +++ b/ModAssistant/Classes/External Interfaces/BeatSaver.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; +using System.Linq; using System.Net; using System.Net.Http.Headers; using System.Runtime.InteropServices; @@ -181,6 +182,30 @@ public static async Task InstallMap(BeatSaverApiResponseMap Map, bool sh } throw new Exception("Zip file not found."); } + + // Verify and patch separate audio file if needed + var hasFingerprintFile = File.Exists(Path.Combine(directory, "fingerprint.bin")); + if (hasFingerprintFile) + { + var noAudioFile = !Directory.EnumerateFiles(directory).Any(file => + { + var ext = Path.GetExtension(file); + return ext == ".egg" || ext == ".ogg" || ext == ".wav"; + }); + if (noAudioFile) + { + var patchSucccess = await SongPatcher.PromptAndPatchSongFromDisk(directory); + if (!patchSucccess) + { + if (showNotification) + { + MessageBox.Show($"{Application.Current.FindResource("OneClick:PatchSong:Failed")}"); + } + throw new Exception("Verification and patching failed."); + } + } + } + return mapName; } diff --git a/ModAssistant/Classes/External Interfaces/SongPatcher.cs b/ModAssistant/Classes/External Interfaces/SongPatcher.cs new file mode 100644 index 00000000..e33ae790 --- /dev/null +++ b/ModAssistant/Classes/External Interfaces/SongPatcher.cs @@ -0,0 +1,91 @@ +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using SaberSongPatcher; +using Application = System.Windows.Application; + +namespace ModAssistant.API +{ + public class SongPatcher + { + public static async Task PromptAndPatchSongFromDisk(string directory) + { + OpenFileDialog openFileDialog = new OpenFileDialog(); + var supportedExtensions = new[] + { + "mp3", + "m4a", + "ogg", + "wav", + "flac", + "aiff", + "wma", + }; + var audioExtensions = string.Join(";", supportedExtensions.Select(ext => $"*.{ext}")); + openFileDialog.Title = (string)Application.Current.FindResource("OneClick:PatchSong:SelectFile"); + openFileDialog.Filter = $"Audio files ({audioExtensions})|{audioExtensions}|All files (*.*)|*.*"; + openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal); + + var success = false; + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + success = await PerformPatch(openFileDialog.FileName, directory); + } + return success; + } + + private static async Task PerformPatch(string inputFile, string mapDirectory) + { + var config = ConfigParser.ParseConfig(true, mapDirectory); + var context = new Context(config); + var inputValidator = new InputValidator(context); + var inputTransformer = new InputTransformer(context); + + var seemsCorrect = await inputValidator.ValidateInput(inputFile, mapDirectory); + if (!seemsCorrect) + { + return false; + } + + var filename = "song.egg"; + var infoFile = Path.Combine(mapDirectory, "info.dat"); + if (!File.Exists(infoFile)) + { + infoFile = Path.Combine(mapDirectory, "Info.dat"); + } + if (File.Exists(infoFile)) + { + try + { + // Try to use the output filename from the info.dat file + using (StreamReader file = File.OpenText(infoFile)) + using (JsonTextReader reader = new JsonTextReader(file)) + { + JObject info = JObject.Load(reader); + var filenameToken = info.Value("_songFilename"); + if (!string.IsNullOrEmpty(filenameToken)) + { + filename = filenameToken; + } + } + } + catch (Exception) + { + } + } + + var outputFile = Path.Combine(mapDirectory, filename); + var success = await inputTransformer.TransformInput(inputFile, outputFile); + if (!success) + { + throw new Exception("Failed to transform audio."); + } + + return true; + } + } +} diff --git a/ModAssistant/Localisation/de.xaml b/ModAssistant/Localisation/de.xaml index 1d02ce20..a190a140 100644 --- a/ModAssistant/Localisation/de.xaml +++ b/ModAssistant/Localisation/de.xaml @@ -216,6 +216,8 @@ Beat Saber Installationspfad nicht gefunden. Installiert: {0} Installation fehlgeschlagen. + Input audio file does not match master audio file for this map. + Select master song audio file {0} OneClick™ Installation Handler registriert! {0} OneClick™ Installation Handler entfernt! Installing: {0} diff --git a/ModAssistant/Localisation/en-DEBUG.xaml b/ModAssistant/Localisation/en-DEBUG.xaml index d7daea69..84f1c15b 100644 --- a/ModAssistant/Localisation/en-DEBUG.xaml +++ b/ModAssistant/Localisation/en-DEBUG.xaml @@ -157,6 +157,8 @@ OneClick:InstallDirNotFound {0} OneClick:InstalledAsset OneClick:AssetInstallFailed + OneClick:PatchSong:Failed + OneClick:PatchSong:SelectFile {0} OneClick:ProtocolHandler:Registered {0} OneClick:ProtocolHandler:Unregistered {0} OneClick:Installing diff --git a/ModAssistant/Localisation/en.xaml b/ModAssistant/Localisation/en.xaml index 21dc8c7d..5685ee13 100644 --- a/ModAssistant/Localisation/en.xaml +++ b/ModAssistant/Localisation/en.xaml @@ -220,6 +220,8 @@ Beat Saber installation path not found. Installed: {0} Failed to install. + Input audio file does not match master audio file for this map. + Select master song audio file {0} OneClick™ Install handlers registered! {0} OneClick™ Install handlers unregistered! Installing: {0} diff --git a/ModAssistant/Localisation/fr.xaml b/ModAssistant/Localisation/fr.xaml index 1cdc5450..3d01c059 100644 --- a/ModAssistant/Localisation/fr.xaml +++ b/ModAssistant/Localisation/fr.xaml @@ -223,6 +223,8 @@ Chemin de l'installation de Beat Saber non trouvé. Installé : {0} Échec de l'installation. + Input audio file does not match master audio file for this map. + Select master song audio file {0} : gestionnaires d'installation OneClick™ inscrits ! {0} : gestionnaires d'installation OneClick™ désinscrits ! Installation de : {0} diff --git a/ModAssistant/Localisation/it.xaml b/ModAssistant/Localisation/it.xaml index d01fde6f..43158f89 100644 --- a/ModAssistant/Localisation/it.xaml +++ b/ModAssistant/Localisation/it.xaml @@ -216,6 +216,8 @@ Directory d'installazione di Beat Saber non trovata. Installato: {0} Non sono riuscito ad installare la mappa. + Input audio file does not match master audio file for this map. + Select master song audio file {0} Registrazione dei gestori OneClick™ riuscita! {0} De-Regitrazione dei gestori OneClick™ riuscita! Installing: {0} diff --git a/ModAssistant/Localisation/ko.xaml b/ModAssistant/Localisation/ko.xaml index c2885356..f150c9d4 100644 --- a/ModAssistant/Localisation/ko.xaml +++ b/ModAssistant/Localisation/ko.xaml @@ -215,6 +215,8 @@ 비트세이버 설치 폴더를 찾을 수 없었습니다. 설치됨: {0} 설치에 실패하였습니다. + Input audio file does not match master audio file for this map. + Select master song audio file {0} OneClick™ 설치 관리자가 등록되었습니다! {0} OneClick™ 설치 관리자가 등록 취소되었습니다! Installing: {0} diff --git a/ModAssistant/Localisation/nl.xaml b/ModAssistant/Localisation/nl.xaml index b7f67fe3..342ec720 100644 --- a/ModAssistant/Localisation/nl.xaml +++ b/ModAssistant/Localisation/nl.xaml @@ -214,6 +214,8 @@ Kon het Beat Saber installatie pad niet vinden {0} Geïnstalleerd Installatie mislukt + Input audio file does not match master audio file for this map. + Select master song audio file {0} OneClick™ Installeer afhandelingen geregistreerd! {0} OneClick™ Install afhandelingen uitgeregistreerd! {0} word geïnstalleerd diff --git a/ModAssistant/Localisation/ru.xaml b/ModAssistant/Localisation/ru.xaml index 8b643492..628e4fdb 100644 --- a/ModAssistant/Localisation/ru.xaml +++ b/ModAssistant/Localisation/ru.xaml @@ -216,6 +216,8 @@ Установочный путь к Beat Saber не найден. Установлено: {0} Ошибка установки. + Input audio file does not match master audio file for this map. + Select master song audio file {0} OneClick™ установки зарегистрированы {0} OneClick™ установки не зарегистрированы! Установка: {0} diff --git a/ModAssistant/Localisation/sv.xaml b/ModAssistant/Localisation/sv.xaml index 1d973dec..07343744 100644 --- a/ModAssistant/Localisation/sv.xaml +++ b/ModAssistant/Localisation/sv.xaml @@ -205,6 +205,8 @@ Det gick inte att ladda ned låten. Det kan vara strul med BeatSaver eller din internetuppkoppling. Misslyckades med att ladda ned låtens ZIP-fil. + Input audio file does not match master audio file for this map. + Select master song audio file Det gick inte att hitta installationsvägen för Beat Saber. Installerade: {0} Misslyckades med att installera. diff --git a/ModAssistant/Localisation/zh.xaml b/ModAssistant/Localisation/zh.xaml index 8a048edc..9205c5bd 100644 --- a/ModAssistant/Localisation/zh.xaml +++ b/ModAssistant/Localisation/zh.xaml @@ -215,6 +215,8 @@ 找不到Beat Saber安装路径。 已添加:{0} 添加失败。 + Input audio file does not match master audio file for this map. + Select master song audio file {0} OneClick™ 一键添加处理程序已注册! {0} OneClick™ 一键添加处理程序已移除! 正在下载:{0} diff --git a/ModAssistant/ModAssistant.csproj b/ModAssistant/ModAssistant.csproj index 48e6bfb7..748dd096 100644 --- a/ModAssistant/ModAssistant.csproj +++ b/ModAssistant/ModAssistant.csproj @@ -1,4 +1,4 @@ - + @@ -13,6 +13,8 @@ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 true + + AnyCPU @@ -37,13 +39,63 @@ Resources\icon.ico + + ..\packages\FFmpeg.AutoGen.4.2.0\lib\net45\FFmpeg.AutoGen.dll + + + ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Newtonsoft.Json.Schema.3.0.13\lib\net45\Newtonsoft.Json.Schema.dll + + + ..\packages\NLog.4.7.3\lib\net45\NLog.dll + + + ..\packages\protobuf-net.3.0.29\lib\net461\protobuf-net.dll + + + ..\packages\protobuf-net.Core.3.0.29\lib\net461\protobuf-net.Core.dll + + + ..\packages\SaberSongPatcher.1.0.2\lib\netstandard2.0\SaberSongPatcherCommon.dll + + + ..\packages\SoundFingerprinting.7.4.12\lib\netstandard2.0\SoundFingerprinting.dll + + + ..\packages\SoundFingerprinting.Emy.7.4.12\lib\netstandard2.0\SoundFingerprinting.Emy.dll + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll + + + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + + + ..\packages\System.ServiceModel.Primitives.4.7.0\lib\net461\System.ServiceModel.Primitives.dll + + @@ -60,6 +112,9 @@ + + ..\packages\Xabe.FFmpeg.4.1.1\lib\netstandard2.0\Xabe.FFmpeg.dll + @@ -69,6 +124,7 @@ + @@ -290,6 +346,7 @@ ResXFileCodeGenerator Resources.Designer.cs + PublicSettingsSingleFileGenerator Settings.Designer.cs @@ -305,4 +362,11 @@ - \ No newline at end of file + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + diff --git a/ModAssistant/packages.config b/ModAssistant/packages.config new file mode 100644 index 00000000..f32b90ed --- /dev/null +++ b/ModAssistant/packages.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file