diff --git a/ModManager/MainWindow.xaml.cs b/ModManager/MainWindow.xaml.cs index 1148a7b1..75ef548f 100644 --- a/ModManager/MainWindow.xaml.cs +++ b/ModManager/MainWindow.xaml.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Threading.Tasks; using System.Windows; +using Anno.Utils; using Imya.UI.Properties; using Imya.UI.Utils; using Imya.Utils; @@ -47,6 +48,9 @@ public MainWindow() if (result is true) GameSetupManager.Instance.RemoveModloader(); } + + // initialize self-updater + SelfUpdater.CheckForUpdate(GithubClientProvider.Client, "anno-mods", "iModYourAnno"); } public void SetUpEmbeddedConsole() diff --git a/ModManager/Utils/SelfUpdater.cs b/ModManager/Utils/SelfUpdater.cs new file mode 100644 index 00000000..16413c5f --- /dev/null +++ b/ModManager/Utils/SelfUpdater.cs @@ -0,0 +1,60 @@ +using System; +using System.Diagnostics; +using System.Threading.Tasks; +using System.Windows; +using Octokit; + +namespace Anno.Utils +{ + internal class SelfUpdater + { + public static void CheckForUpdate(GitHubClient client, string owner, string repo) + { + Task.Run(async () => + { + var availableUpdate = await IsUpdateAvailableAsync(client, owner, repo); + if (availableUpdate is not null) + { + var answer = MessageBox.Show($"iModYourAnno {availableUpdate.TagName} is available.\n\nDo you want to download it now?", + "Update Available", MessageBoxButton.YesNo); + if (answer == MessageBoxResult.Yes) + { + OpenReleasePage(availableUpdate); + } + } + }); + } + + public async static Task IsUpdateAvailableAsync(GitHubClient client, string owner, string repo) + { + var latest = await client.Repository.Release.GetLatest(owner, repo); + if (latest is null) return null; + + Console.WriteLine( + "The latest release is tagged at {0} and is named {1}", + latest.TagName, + latest.Name); + + var latestVersion = new Version(latest.TagName[1..]); + var currentVersion = GetCurrentVersion(); + + return (latestVersion > currentVersion) ? latest : null; + } + + public static void OpenReleasePage(Release release) + { + var info = new ProcessStartInfo(release.HtmlUrl) + { + UseShellExecute = true, + }; + Process.Start(info); + } + + public static Version GetCurrentVersion() + { + System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); + FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); + return new Version((fvi.FileVersion ?? "v0.0")[1..].Split('-')[0]); + } + } +} diff --git a/ModManager_Classes/Models/Mod.cs b/ModManager_Classes/Models/Mod.cs index 2811bea7..e6acaee7 100644 --- a/ModManager_Classes/Models/Mod.cs +++ b/ModManager_Classes/Models/Mod.cs @@ -142,6 +142,25 @@ public Mod (string folderName, Modinfo? modinfo, string basePath) // TODO move to separate async? var info = new DirectoryInfo(FullModPath); SizeInMB = (float)Math.Round((decimal)info.EnumerateFiles("*", SearchOption.AllDirectories).Sum(x => x.Length) / 1024 / 1024, 1); + + string[] modinfos = Directory.GetFiles(Path.Combine(basePath, folderName), "modinfo.json", SearchOption.AllDirectories); + if (modinfos.Length > 1) + { + SubMods = new List(); + foreach (var submodinfo in modinfos) + { + if (submodinfo == Path.Combine(basePath, folderName, "modinfo.json")) + { + continue; + } + + Mod? submod = TryFromFolder(Path.GetDirectoryName(submodinfo) ?? ""); + if (submod is not null) + { + SubMods.Add(submod); + } + } + } } public void InitImageAsFilepath(String ImagePath) @@ -310,6 +329,10 @@ public bool IsUpdateOf(Mod? target) } #endregion + #region Sub mods + public List? SubMods { get; private set; } + #endregion + public ModStatus GetStatus() { return (Attributes.GetByType(AttributeType.ModStatus) as ModStatusAttribute)?.Status ?? ModStatus.Default; diff --git a/ModManager_Classes/Models/ModCollection.cs b/ModManager_Classes/Models/ModCollection.cs index 9de3d74a..5f75d936 100644 --- a/ModManager_Classes/Models/ModCollection.cs +++ b/ModManager_Classes/Models/ModCollection.cs @@ -118,7 +118,7 @@ private static void AutofixSubfolders(string modsPath) { foreach (var folder in Directory.EnumerateDirectories(modsPath)) { - if (Directory.Exists(Path.Combine(folder, "data"))) + if (Directory.Exists(Path.Combine(folder, "data")) || File.Exists(Path.Combine(folder, "modinfo.json"))) continue; var potentialMods = DirectoryEx.FindFolder(folder, "data").Select(x => Path.GetDirectoryName(x)!); diff --git a/ModManager_Classes/Utils/InstallationManager.cs b/ModManager_Classes/Utils/InstallationManager.cs index 7c9981ff..03c3a6d2 100644 --- a/ModManager_Classes/Utils/InstallationManager.cs +++ b/ModManager_Classes/Utils/InstallationManager.cs @@ -1,11 +1,6 @@ using Imya.Models; using Imya.Models.Collections; using Imya.Models.Installation; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Downloader; using Imya.Models.NotifyPropertyChanged; @@ -266,7 +261,9 @@ private async Task MoveModsAsync(IUnpackableInstallation unpackable) if (unpackable.CancellationToken.IsCancellationRequested) return; unpackable.Status = InstallationStatus.MovingFiles; - var newCollection = await ModCollectionLoader.LoadFrom(unpackable.UnpackTargetPath); + + var newCollection = new ModCollection(unpackable.UnpackTargetPath, autofixSubfolder: true); + await newCollection.LoadModsAsync(); //async waiting await Task.Run(() => _moveIntoSem.WaitOne(), unpackable.CancellationToken); if (!unpackable.CancellationToken.IsCancellationRequested) diff --git a/ModManager_Classes/Utils/ModCollectionLoader.cs b/ModManager_Classes/Utils/ModCollectionLoader.cs deleted file mode 100644 index cb22ff83..00000000 --- a/ModManager_Classes/Utils/ModCollectionLoader.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.IO.Compression; -using Imya.Models; -using Imya.Models.Installation; - -namespace Imya.Utils -{ - /// - /// Install mods from zip file - might depracate this honestly - /// - public class ModCollectionLoader - { - public static async Task LoadFrom(String Filepath) - { - var collection = new ModCollection(Filepath, autofixSubfolder: true); - await collection.LoadModsAsync(); - return collection; - } - } -} diff --git a/ModManager_Classes/Validation/ModCompatibilityValidator.cs b/ModManager_Classes/Validation/ModCompatibilityValidator.cs index 8345bceb..dd117aa0 100644 --- a/ModManager_Classes/Validation/ModCompatibilityValidator.cs +++ b/ModManager_Classes/Validation/ModCompatibilityValidator.cs @@ -43,7 +43,9 @@ private static IEnumerable GetUnresolvedDependencies(Modinfo modinfo, IR foreach (var dep in modinfo.ModDependencies) { - if (!collection.Any(x => x.Modinfo.ModID is not null && x.Modinfo.ModID.Equals(dep) && x.IsActiveAndValid)) + if (!collection.Any(x => x.Modinfo.ModID is not null + && (x.Modinfo.ModID.Equals(dep) || x.SubMods?.Find(submod => submod.ModID.Equals(dep)) is not null) + && x.IsActiveAndValid)) yield return dep; } } diff --git a/ModManager_Classes/Validation/ModContentValidator.cs b/ModManager_Classes/Validation/ModContentValidator.cs index ab2cf075..ee082d32 100644 --- a/ModManager_Classes/Validation/ModContentValidator.cs +++ b/ModManager_Classes/Validation/ModContentValidator.cs @@ -18,26 +18,11 @@ public void Validate(IEnumerable changed, IReadOnlyCollection all) private static void ValidateSingle(Mod mod) { - mod.Attributes.RemoveAttributesByType(AttributeType.ModContentInSubfolder); - if (mod.IsRemoved || !Directory.Exists(mod.FullModPath)) { mod.IsRemoved = true; return; } - - string dataPath = Path.Combine(mod.FullModPath, "data"); - if (!Directory.Exists(dataPath)) - { - // data/ doesn't exist, that's odd - - var foundFolders = Directory.GetDirectories(mod.FullModPath, "data", SearchOption.AllDirectories); - if (foundFolders.Length > 0) - { - // there's a data/ somewhere deeper, probably a mistake then - mod.Attributes.AddAttribute(new GenericAttribute() { AttributeType = AttributeType.ModContentInSubfolder, Description = TextManager.Instance.GetText("ATTRIBUTE_MODCONTENTSUBFOLDER") }); - } - } } } }