diff --git a/ModAssistant/Localisation/en-DEBUG.xaml b/ModAssistant/Localisation/en-DEBUG.xaml
index 44e62dde..0e749032 100644
--- a/ModAssistant/Localisation/en-DEBUG.xaml
+++ b/ModAssistant/Localisation/en-DEBUG.xaml
@@ -60,6 +60,12 @@
Mods:UninstallButton
Mods:LoadFailed
Mods:CheckingInstalledMods
+ Mods:GameUpdatedPrompt:Title
+ Mods:GameUpdatedPrompt:OkCancel
+ Mods:FailedToSelect:Title
+ Mods:FailedToSelect:Body1
+ Mods:FailedToSelect:Body2
+ Mods:CheckingPreviousMods
Mods:LoadingMods
Mods:FinishedLoadingMods
Mods:NoMods
diff --git a/ModAssistant/Localisation/en.xaml b/ModAssistant/Localisation/en.xaml
index 60898af1..f789b278 100644
--- a/ModAssistant/Localisation/en.xaml
+++ b/ModAssistant/Localisation/en.xaml
@@ -91,6 +91,12 @@
Uninstall
Could not load mods list
Checking installed mods
+ Reselect mods?
+ The game has updated since you last modded, would you like to automatically re-select the mods you had installed previously?
+ Failed to select {0} mods
+ The following mods could not be found and weren't selected:
+ These mods might not be updated for the current game version.
+ Checking previously installed mods
Loading Mods
Finished loading mods
No mods available for this version of Beat Saber
diff --git a/ModAssistant/Pages/Mods.xaml.cs b/ModAssistant/Pages/Mods.xaml.cs
index 29d6c96d..bea7fddd 100644
--- a/ModAssistant/Pages/Mods.xaml.cs
+++ b/ModAssistant/Pages/Mods.xaml.cs
@@ -3,6 +3,7 @@
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@@ -30,6 +31,7 @@ public sealed partial class Mods : Page
public static List InstalledMods = new List();
public static List ManifestsToMatch = new List();
public List CategoryNames = new List();
+ public static List MissingOldMods = new List();
public CollectionView view;
public bool PendingChanges;
@@ -124,6 +126,31 @@ public async Task LoadMods()
DescriptionColumn.Width = 800;
}
+ string lastModdedVersion = CheckPreviousInstallDirs();
+ if (lastModdedVersion != null &&
+ !DirectoryContainsMods(Path.Combine(App.BeatSaberInstallDirectory, "Plugins")) &&
+ !DirectoryContainsMods(Path.Combine(App.BeatSaberInstallDirectory, "IPA/Pending/Plugins")))
+ {
+ string body = (string)FindResource("Mods:GameUpdatedPrompt:OkCancel");
+ string title = (string)FindResource("Mods:GameUpdatedPrompt:Title");
+
+ var reinstallMods = System.Windows.Forms.MessageBox.Show(body, title, MessageBoxButtons.OKCancel) == DialogResult.OK;
+ if (reinstallMods) {
+ MainWindow.Instance.MainText = $"{FindResource("Mods:CheckingPreviousMods")}...";
+ await Task.Run(async () => await SelectPreviousMods(lastModdedVersion));
+ InstalledColumn.Width = double.NaN;
+ UninstallColumn.Width = 70;
+ DescriptionColumn.Width = 750;
+ if (MissingOldMods.Count > 0) {
+ string notSelectedTitle = string.Format((string)FindResource("Mods:FailedToSelect:Title"), MissingOldMods.Count);
+ string notSelectedBody1 = (string)FindResource("Mods:FailedToSelect:Body1");
+ string notSelectedBody2 = (string)FindResource("Mods:FailedToSelect:Body2");
+
+ System.Windows.Forms.MessageBox.Show($"{notSelectedBody1}\n{string.Join(",\n", MissingOldMods)}\n\n{notSelectedBody2}", notSelectedTitle, MessageBoxButtons.OK);
+ }
+ }
+ }
+
MainWindow.Instance.MainText = $"{FindResource("Mods:LoadingMods")}...";
await Task.Run(async () => await PopulateModsList());
@@ -190,6 +217,15 @@ public async Task CheckInstalledMods()
CheckInstallDir("Libs");
}
+ public async Task SelectPreviousMods(string previousModsDirectory)
+ {
+ if(AllModsList == null) await GetAllMods();
+
+ CheckInstallDir(previousModsDirectory, true);
+ CheckInstallDir("Libs");
+ //CheckPreviousInstallDirs();
+ }
+
public async Task GetAllMods()
{
var resp = await HttpClient.GetAsync(Utils.Constants.BeatModsAPIUrl + "mod");
@@ -206,7 +242,52 @@ public async Task GetAllMods()
}
}
- private void CheckInstallDir(string directory)
+ private SemVersion SemverForPluginFolder(string directory)
+ {
+ string versionString = directory.Substring(directory.LastIndexOf("Old") + 3, directory.Length - directory.LastIndexOf("Plugins")).Trim();
+ SemVersion semver;
+ if (!SemVersion.TryParse(versionString, out semver)) return null;
+ return semver;
+ }
+
+ private int CompareInstallDirs(string a, string b)
+ {
+ SemVersion semverA = SemverForPluginFolder(a);
+ SemVersion semverB = SemverForPluginFolder(b);
+ if (semverA == null) return 1;
+ else if(semverB == null) return 0;
+
+ return semverB.CompareTo(semverA);
+ }
+
+ private bool DirectoryContainsMods(string directory)
+ {
+ if (Directory.Exists(directory))
+ {
+ foreach (string file in Directory.GetFileSystemEntries(Path.Combine(App.BeatSaberInstallDirectory, directory)))
+ {
+ string fileExtension = Path.GetExtension(file);
+
+ if (File.Exists(file) && (fileExtension == ".dll" || fileExtension == ".manifest")) return true;
+ }
+ }
+ return false;
+ }
+
+ private string CheckPreviousInstallDirs()
+ {
+ if (!Directory.Exists(App.BeatSaberInstallDirectory)) return null;
+
+ string[] directories = Directory.GetDirectories(App.BeatSaberInstallDirectory, "Old*Plugins");
+ if (directories.Length == 0) return null;
+ Array.Sort(directories, CompareInstallDirs);
+
+ foreach(string directory in directories) if (DirectoryContainsMods(directory)) return directory;
+
+ return null;
+ }
+
+ private void CheckInstallDir(string directory, bool setFailedMods = false)
{
if (!Directory.Exists(Path.Combine(App.BeatSaberInstallDirectory, directory)))
{
@@ -241,6 +322,12 @@ private void CheckInstallDir(string directory)
AddDetectedMod(mod);
}
}
+ else if (setFailedMods)
+ {
+ string fileName = Path.GetFileNameWithoutExtension(file);
+ if (!MissingOldMods.Contains(fileName)) MissingOldMods.Add(fileName);
+ // maybe hook into the manifest to get the actual name. too lazy for now.
+ }
}
}
}
@@ -274,7 +361,7 @@ private void AddDetectedMod(Mod mod)
if (!InstalledMods.Contains(mod))
{
InstalledMods.Add(mod);
- if (App.SelectInstalledMods && !DefaultMods.Contains(mod.name))
+ if (!DefaultMods.Contains(mod.name))
{
DefaultMods.Add(mod.name);
}