diff --git a/Knossos.NET/Models/Mod.cs b/Knossos.NET/Models/Mod.cs index e03cac6a..f2b6ae80 100644 --- a/Knossos.NET/Models/Mod.cs +++ b/Knossos.NET/Models/Mod.cs @@ -39,22 +39,6 @@ public enum ModSource local } - /// - /// Nebula int values, do not change - /// It is not clear what can each one of the roles do and what not - /// - public enum ModMemberRole - { - Owner = 0, - Manager = 10, - Uploader = 20, - Tester = 30 - } - - /* - - */ - /// /// The "mod class" variables math the json properties for the mod.json file that is located at the root of the mod folder. /// In order to maintain compatibility with other launchers all properties saved in the mod.json file must be @@ -1030,315 +1014,4 @@ public static bool IsMetaUpdate(Mod modA, Mod modB) return null; } } - - public class ModMember - { - public ModMemberRole role { get; set; } - public string user { get; set; } = string.Empty; - } - - public class ModPackage - { - public string name { get; set; } = string.Empty; // required - public string? notes { get; set; } = string.Empty; // optional - /* - optional, default: "recommended" - A feature can be: - - "required" (always installed with the mod, in fact these are the base files of the mod), - - "recommended" (automatically selected for installation, but the user can skip them), - - "optional" (not automatically selected, but user can add them during the install process) - */ - public string? status { get; set; } // "" - public ModDependency[]? dependencies { get; set; } = new ModDependency[0]; - public string? environment { get; set; } // optional, boolean expression like "windows && X86_64 && (sse || sse2)" - public string? folder { get; set; } - [JsonPropertyName("is_vp")] - public bool isVp { get; set; } // optional, whether Knossos should pack the files in a VP on upload, default: false - public ModFile[]? files { get; set; } = new ModFile[0]; - public ModFilelist[]? filelist { get; set; } = new ModFilelist[0]; - public List? executables { get; set; } = new List();// optional - [JsonPropertyName("check_notes")] - public object? checkNotes { get; set; } - - /* Knet Only */ - /// - /// used for pkg display in a checkbox. - /// NOT Saved in the json - /// - [JsonIgnore] - public bool isSelected { get; set; } = false; - /// - /// used for display (to enable/disabled chkbox) and to enable/disable the package in devmode - /// Saved in the json - /// - public bool isEnabled { get; set; } = true; - /// - /// Used to display checkbox tooltip - /// NOT saved in the Json - /// - [JsonIgnore] - public string tooltip { get; set; } = string.Empty; - /// - /// Used to indicate a pkg is needed during mod install checkbox selection - /// Used to change checkbox foreground color during mod install/modify display - /// - [JsonIgnore] - public bool isRequired { get; set; } = false; - [JsonIgnore] - public int buildScore { get; set; } = 0; - } - - public class ModDependency - { - public string id { get; set; } = string.Empty; // required - public string? version { get; set; } // required, https://getcomposer.org/doc/01-basic-usage.md#package-versions - public List? packages { get; set; } // optional, specifies which optional and recommended packages are also required - - /// - /// Used to store the original dependency reference during mod.GetMissingDependencies - /// Useful to track down the original pkg this dependency belongs to - /// mod.FindPackageWithDependency() - /// Not saved in Json - /// - [JsonIgnore] - public ModDependency? originalDependency; - - /// - /// Returns the best installed mod that meets this dependency by semantic version, null if none. - /// Also returns null if the ID is a FSO build. - /// - /// Mod or null - public Mod? SelectMod() - { - var mods = Knossos.GetInstalledModList(id); - Mod? validMod = null; - - foreach (var mod in mods) - { - - try - { - if (SemanticVersion.SastifiesDependency(version, mod.version)) - { - if (validMod == null) - { - validMod = mod; - } - else - { - if (SemanticVersion.Compare(mod.version, validMod.version) > 0) - { - validMod = mod; - } - } - } - } catch (Exception ex) - { - Log.Add(Log.LogSeverity.Error, "Mod.SelectMod()", "Mod: "+mod.title + " " + ex.Message); - } - } - return validMod; - } - - /// - /// Returns the best available mod on nebula that meets this dependency by semantic version, null if none. - /// Takes an optional list with all mods, if passed it will use that list intead of checking the repo.json again - /// - /// - /// Mod or null - public async Task SelectModNebula(List? mods = null) - { - if(mods == null) - { - mods = await Nebula.GetAllModsWithID(id); - } - - Mod? validMod = null; - - foreach (var mod in mods) - { - if (mod.id == id && SemanticVersion.SastifiesDependency(version, mod.version)) - { - if (validMod == null) - { - validMod = mod; - } - else - { - if (mod.type == ModType.engine) - { - var stabilityV = FsoBuild.GetFsoStability(validMod.stability, validMod.id); - var stabilityM = FsoBuild.GetFsoStability(mod.stability, mod.id); - //inverted stability comparison - if (stabilityV > stabilityM || stabilityV == stabilityM && SemanticVersion.Compare(mod.version, validMod.version) > 0) - { - validMod = mod; - } - } - else - { - if (SemanticVersion.Compare(mod.version, validMod.version) > 0) - { - validMod = mod; - } - } - } - } - } - - return validMod; - } - - /// - /// Returns the best installed build that meets this dependency by semantic version, null if none. - /// Optional: Only select builds with at least one valid executabl - /// - /// FsoBuild or null - public FsoBuild? SelectBuild(bool onlyWithValidExecutable = false) - { - FsoBuild? validBuild = null; - - foreach (var build in Knossos.GetInstalledBuildsList(id, FsoStability.Stable)) - { - if ((!onlyWithValidExecutable || onlyWithValidExecutable && build.IsValidBuild()) && SemanticVersion.SastifiesDependency(version, build.version)) - { - - if (validBuild == null) - { - validBuild = build; - } - else - { - if (SemanticVersion.Compare(build.version, validBuild.version) > 0) - { - validBuild = build; - } - } - } - } - - if(validBuild == null) - { - foreach (var build in Knossos.GetInstalledBuildsList(id, FsoStability.RC)) - { - if ((!onlyWithValidExecutable || onlyWithValidExecutable && build.IsValidBuild()) && SemanticVersion.SastifiesDependency(version, build.version)) - { - - if (validBuild == null) - { - validBuild = build; - } - else - { - if (SemanticVersion.Compare(build.version, validBuild.version) > 0) - { - validBuild = build; - } - } - } - } - } - - if (validBuild == null) - { - foreach (var build in Knossos.GetInstalledBuildsList(id, FsoStability.Nightly)) - { - if ((!onlyWithValidExecutable || onlyWithValidExecutable && build.IsValidBuild()) && SemanticVersion.SastifiesDependency(version, build.version)) - { - - if (validBuild == null) - { - validBuild = build; - } - else - { - if (SemanticVersion.Compare(build.version, validBuild.version) > 0) - { - validBuild = build; - } - } - } - } - } - - if (validBuild == null) - { - foreach (var build in Knossos.GetInstalledBuildsList(id, FsoStability.Custom)) - { - if ((!onlyWithValidExecutable || onlyWithValidExecutable && build.IsValidBuild()) && SemanticVersion.SastifiesDependency(version, build.version)) - { - - if (validBuild == null) - { - validBuild = build; - } - else - { - if (SemanticVersion.Compare(build.version, validBuild.version) > 0) - { - validBuild = build; - } - } - } - } - } - - return validBuild; - } - - /// - /// returns id + version - /// - public override string ToString() - { - return id + " " + version; - } - } - - public class ModFile - { - public string? filename { get; set; } - public string? dest { get; set; } // "" - public string[]? checksum { get; set; } // sha256, value - public Int64 filesize { get; set; } // Size in bytes - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] - public string[]? urls { get; set; } // The URLs are full URLs (they contain the filename). - } - - public class ModFilelist - { - public string? filename { get; set; } // file path - public string? archive { get; set; } - [JsonPropertyName("orig_name")] - public string? origName { get; set; } // name in archive - public string[]? checksum { get; set; } // sha256, value - } - - public class ModExecutable - { - public string? file { get; set; } // required, path to the executable (*.exe file on Windows), relative to the mod folder - public string? label { get; set; } // optional, should be null for release builds and contain the name for others - public ModProperties? properties { get; set; } - - [JsonIgnore] - public int score { get; set; } = 0; - } - - /// - /// This is generated from the enviroment string at runtime - /// - public class ModProperties - { - public bool x64 { get; set; } - public bool sse2 { get; set; } - public bool avx { get; set; } - public bool avx2 { get; set; } - - /* Knossos.NET added */ - public bool arm64 { get; set; } - public bool arm32 { get; set; } - public bool riscv32 { get; set; } - public bool riscv64 { get; set; } - public bool other { get; set; } - } } diff --git a/Knossos.NET/Models/ModDependency.cs b/Knossos.NET/Models/ModDependency.cs new file mode 100644 index 00000000..8135c764 --- /dev/null +++ b/Knossos.NET/Models/ModDependency.cs @@ -0,0 +1,216 @@ +using Knossos.NET.Classes; +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Knossos.NET.Models +{ + public class ModDependency + { + public string id { get; set; } = string.Empty; // required + public string? version { get; set; } // required, https://getcomposer.org/doc/01-basic-usage.md#package-versions + public List? packages { get; set; } // optional, specifies which optional and recommended packages are also required + + /// + /// Used to store the original dependency reference during mod.GetMissingDependencies + /// Useful to track down the original pkg this dependency belongs to + /// mod.FindPackageWithDependency() + /// Not saved in Json + /// + [JsonIgnore] + public ModDependency? originalDependency; + + /// + /// Returns the best installed mod that meets this dependency by semantic version, null if none. + /// Also returns null if the ID is a FSO build. + /// + /// Mod or null + public Mod? SelectMod() + { + var mods = Knossos.GetInstalledModList(id); + Mod? validMod = null; + + foreach (var mod in mods) + { + + try + { + if (SemanticVersion.SastifiesDependency(version, mod.version)) + { + if (validMod == null) + { + validMod = mod; + } + else + { + if (SemanticVersion.Compare(mod.version, validMod.version) > 0) + { + validMod = mod; + } + } + } + } + catch (Exception ex) + { + Log.Add(Log.LogSeverity.Error, "Mod.SelectMod()", "Mod: " + mod.title + " " + ex.Message); + } + } + return validMod; + } + + /// + /// Returns the best available mod on nebula that meets this dependency by semantic version, null if none. + /// Takes an optional list with all mods, if passed it will use that list intead of checking the repo.json again + /// + /// + /// Mod or null + public async Task SelectModNebula(List? mods = null) + { + if (mods == null) + { + mods = await Nebula.GetAllModsWithID(id); + } + + Mod? validMod = null; + + foreach (var mod in mods) + { + if (mod.id == id && SemanticVersion.SastifiesDependency(version, mod.version)) + { + if (validMod == null) + { + validMod = mod; + } + else + { + if (mod.type == ModType.engine) + { + var stabilityV = FsoBuild.GetFsoStability(validMod.stability, validMod.id); + var stabilityM = FsoBuild.GetFsoStability(mod.stability, mod.id); + //inverted stability comparison + if (stabilityV > stabilityM || stabilityV == stabilityM && SemanticVersion.Compare(mod.version, validMod.version) > 0) + { + validMod = mod; + } + } + else + { + if (SemanticVersion.Compare(mod.version, validMod.version) > 0) + { + validMod = mod; + } + } + } + } + } + + return validMod; + } + + /// + /// Returns the best installed build that meets this dependency by semantic version, null if none. + /// Optional: Only select builds with at least one valid executabl + /// + /// FsoBuild or null + public FsoBuild? SelectBuild(bool onlyWithValidExecutable = false) + { + FsoBuild? validBuild = null; + + foreach (var build in Knossos.GetInstalledBuildsList(id, FsoStability.Stable)) + { + if ((!onlyWithValidExecutable || onlyWithValidExecutable && build.IsValidBuild()) && SemanticVersion.SastifiesDependency(version, build.version)) + { + + if (validBuild == null) + { + validBuild = build; + } + else + { + if (SemanticVersion.Compare(build.version, validBuild.version) > 0) + { + validBuild = build; + } + } + } + } + + if (validBuild == null) + { + foreach (var build in Knossos.GetInstalledBuildsList(id, FsoStability.RC)) + { + if ((!onlyWithValidExecutable || onlyWithValidExecutable && build.IsValidBuild()) && SemanticVersion.SastifiesDependency(version, build.version)) + { + + if (validBuild == null) + { + validBuild = build; + } + else + { + if (SemanticVersion.Compare(build.version, validBuild.version) > 0) + { + validBuild = build; + } + } + } + } + } + + if (validBuild == null) + { + foreach (var build in Knossos.GetInstalledBuildsList(id, FsoStability.Nightly)) + { + if ((!onlyWithValidExecutable || onlyWithValidExecutable && build.IsValidBuild()) && SemanticVersion.SastifiesDependency(version, build.version)) + { + + if (validBuild == null) + { + validBuild = build; + } + else + { + if (SemanticVersion.Compare(build.version, validBuild.version) > 0) + { + validBuild = build; + } + } + } + } + } + + if (validBuild == null) + { + foreach (var build in Knossos.GetInstalledBuildsList(id, FsoStability.Custom)) + { + if ((!onlyWithValidExecutable || onlyWithValidExecutable && build.IsValidBuild()) && SemanticVersion.SastifiesDependency(version, build.version)) + { + + if (validBuild == null) + { + validBuild = build; + } + else + { + if (SemanticVersion.Compare(build.version, validBuild.version) > 0) + { + validBuild = build; + } + } + } + } + } + + return validBuild; + } + + /// + /// returns id + version + /// + public override string ToString() + { + return id + " " + version; + } + } +} diff --git a/Knossos.NET/Models/ModExecutable.cs b/Knossos.NET/Models/ModExecutable.cs new file mode 100644 index 00000000..0cd52df3 --- /dev/null +++ b/Knossos.NET/Models/ModExecutable.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; + +namespace Knossos.NET.Models +{ + public class ModExecutable + { + public string? file { get; set; } // required, path to the executable (*.exe file on Windows), relative to the mod folder + public string? label { get; set; } // optional, should be null for release builds and contain the name for others + public ModProperties? properties { get; set; } + + [JsonIgnore] + public int score { get; set; } = 0; + } +} diff --git a/Knossos.NET/Models/ModFile.cs b/Knossos.NET/Models/ModFile.cs new file mode 100644 index 00000000..674e859f --- /dev/null +++ b/Knossos.NET/Models/ModFile.cs @@ -0,0 +1,15 @@ +using System; +using System.Text.Json.Serialization; + +namespace Knossos.NET.Models +{ + public class ModFile + { + public string? filename { get; set; } + public string? dest { get; set; } // "" + public string[]? checksum { get; set; } // sha256, value + public Int64 filesize { get; set; } // Size in bytes + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public string[]? urls { get; set; } // The URLs are full URLs (they contain the filename). + } +} diff --git a/Knossos.NET/Models/ModFileList.cs b/Knossos.NET/Models/ModFileList.cs new file mode 100644 index 00000000..cb3e66df --- /dev/null +++ b/Knossos.NET/Models/ModFileList.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace Knossos.NET.Models +{ + public class ModFilelist + { + public string? filename { get; set; } // file path + public string? archive { get; set; } + [JsonPropertyName("orig_name")] + public string? origName { get; set; } // name in archive + public string[]? checksum { get; set; } // sha256, value + } +} diff --git a/Knossos.NET/Models/ModMember.cs b/Knossos.NET/Models/ModMember.cs new file mode 100644 index 00000000..707844c2 --- /dev/null +++ b/Knossos.NET/Models/ModMember.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Knossos.NET.Models +{ + /// + /// Nebula int values, do not change + /// It is not clear what can each one of the roles do and what not + /// + public enum ModMemberRole + { + Owner = 0, + Manager = 10, + Uploader = 20, + Tester = 30 + } + + public class ModMember + { + public ModMemberRole role { get; set; } + public string user { get; set; } = string.Empty; + } +} diff --git a/Knossos.NET/Models/ModPackage.cs b/Knossos.NET/Models/ModPackage.cs new file mode 100644 index 00000000..e101d36b --- /dev/null +++ b/Knossos.NET/Models/ModPackage.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Knossos.NET.Models +{ + public class ModPackage + { + public string name { get; set; } = string.Empty; // required + public string? notes { get; set; } = string.Empty; // optional + /* + optional, default: "recommended" + A feature can be: + - "required" (always installed with the mod, in fact these are the base files of the mod), + - "recommended" (automatically selected for installation, but the user can skip them), + - "optional" (not automatically selected, but user can add them during the install process) + */ + public string? status { get; set; } // "" + public ModDependency[]? dependencies { get; set; } = new ModDependency[0]; + public string? environment { get; set; } // optional, boolean expression like "windows && X86_64 && (sse || sse2)" + public string? folder { get; set; } + [JsonPropertyName("is_vp")] + public bool isVp { get; set; } // optional, whether Knossos should pack the files in a VP on upload, default: false + public ModFile[]? files { get; set; } = new ModFile[0]; + public ModFilelist[]? filelist { get; set; } = new ModFilelist[0]; + public List? executables { get; set; } = new List();// optional + [JsonPropertyName("check_notes")] + public object? checkNotes { get; set; } + + /* Knet Only */ + /// + /// used for pkg display in a checkbox. + /// NOT Saved in the json + /// + [JsonIgnore] + public bool isSelected { get; set; } = false; + /// + /// used for display (to enable/disabled chkbox) and to enable/disable the package in devmode + /// Saved in the json + /// + public bool isEnabled { get; set; } = true; + /// + /// Used to display checkbox tooltip + /// NOT saved in the Json + /// + [JsonIgnore] + public string tooltip { get; set; } = string.Empty; + /// + /// Used to indicate a pkg is needed during mod install checkbox selection + /// Used to change checkbox foreground color during mod install/modify display + /// + [JsonIgnore] + public bool isRequired { get; set; } = false; + [JsonIgnore] + public int buildScore { get; set; } = 0; + } +} diff --git a/Knossos.NET/Models/ModProperties.cs b/Knossos.NET/Models/ModProperties.cs new file mode 100644 index 00000000..42e661aa --- /dev/null +++ b/Knossos.NET/Models/ModProperties.cs @@ -0,0 +1,20 @@ +namespace Knossos.NET.Models +{ + /// + /// This is generated from the enviroment string at runtime + /// + public class ModProperties + { + public bool x64 { get; set; } + public bool sse2 { get; set; } + public bool avx { get; set; } + public bool avx2 { get; set; } + + /* Knossos.NET added */ + public bool arm64 { get; set; } + public bool arm32 { get; set; } + public bool riscv32 { get; set; } + public bool riscv64 { get; set; } + public bool other { get; set; } + } +}