Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prompt to install previous versions after a game update #396

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ModAssistant/Localisation/en-DEBUG.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@
<sys:String x:Key="Mods:UninstallButton">Mods:UninstallButton</sys:String>
<sys:String x:Key="Mods:LoadFailed">Mods:LoadFailed</sys:String>
<sys:String x:Key="Mods:CheckingInstalledMods">Mods:CheckingInstalledMods</sys:String>
<sys:String x:Key="Mods:GameUpdatedPrompt:Title">Mods:GameUpdatedPrompt:Title</sys:String>
<sys:String x:Key="Mods:GameUpdatedPrompt:OkCancel">Mods:GameUpdatedPrompt:OkCancel</sys:String>
<sys:String x:Key="Mods:FailedToSelect:Title">Mods:FailedToSelect:Title</sys:String>
<sys:String x:Key="Mods:FailedToSelect:Body1">Mods:FailedToSelect:Body1</sys:String>
<sys:String x:Key="Mods:FailedToSelect:Body2">Mods:FailedToSelect:Body2</sys:String>
<sys:String x:Key="Mods:CheckingPreviousMods">Mods:CheckingPreviousMods</sys:String>
<sys:String x:Key="Mods:LoadingMods">Mods:LoadingMods</sys:String>
<sys:String x:Key="Mods:FinishedLoadingMods">Mods:FinishedLoadingMods</sys:String>
<sys:String x:Key="Mods:NoMods">Mods:NoMods</sys:String>
Expand Down
6 changes: 6 additions & 0 deletions ModAssistant/Localisation/en.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@
<sys:String x:Key="Mods:UninstallButton">Uninstall</sys:String>
<sys:String x:Key="Mods:LoadFailed">Could not load mods list</sys:String>
<sys:String x:Key="Mods:CheckingInstalledMods">Checking installed mods</sys:String>
<sys:String x:Key="Mods:GameUpdatedPrompt:Title">Reselect mods?</sys:String>
<sys:String x:Key="Mods:GameUpdatedPrompt:OkCancel">The game has updated since you last modded, would you like to automatically re-select the mods you had installed previously?</sys:String>
<sys:String x:Key="Mods:FailedToSelect:Title">Failed to select {0} mods</sys:String>
<sys:String x:Key="Mods:FailedToSelect:Body1">The following mods could not be found and weren't selected:</sys:String>
<sys:String x:Key="Mods:FailedToSelect:Body2">These mods might not be updated for the current game version.</sys:String>
<sys:String x:Key="Mods:CheckingPreviousMods">Checking previously installed mods</sys:String>
<sys:String x:Key="Mods:LoadingMods">Loading Mods</sys:String>
<sys:String x:Key="Mods:FinishedLoadingMods">Finished loading mods</sys:String>
<sys:String x:Key="Mods:NoMods">No mods available for this version of Beat Saber</sys:String>
Expand Down
91 changes: 89 additions & 2 deletions ModAssistant/Pages/Mods.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -30,6 +31,7 @@ public sealed partial class Mods : Page
public static List<Mod> InstalledMods = new List<Mod>();
public static List<Mod> ManifestsToMatch = new List<Mod>();
public List<string> CategoryNames = new List<string>();
public static List<string> MissingOldMods = new List<string>();
public CollectionView view;
public bool PendingChanges;

Expand Down Expand Up @@ -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());

Expand Down Expand Up @@ -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");
Expand All @@ -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)))
{
Expand Down Expand Up @@ -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.
}
}
}
}
Expand Down Expand Up @@ -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);
}
Expand Down
Loading